Skip to content

JavaScript 核心

JS 核心题考的是:闭包、原型链、this、事件循环、异步编程。答得出原理才算真正理解 JS。

Q1: 什么是闭包?有什么应用和陷阱? 「🟡 中级」

考察点:JS 作用域链的理解深度。

参考答案

  • 闭包:函数可以访问其词法作用域中的变量,即使函数在作用域外执行。本质是函数 + 它引用的外部变量的环境。
  • 应用:数据私有化(模块模式)、函数工厂、柯里化、回调中保持状态。
  • 陷阱:循环中的闭包(var 在 for 循环里共享同一个变量,用 let 或 IIFE 解决);内存泄漏(闭包持有大对象引用无法被 GC)。
javascript
// 经典陷阱
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100); // 输出 3 3 3
}
// 解决:用 let 或 IIFE
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100); // 输出 0 1 2
}

追问延伸

  • 闭包在 V8 里是怎么实现的?
  • 怎么排查闭包导致的内存泄漏?

Q2: 原型链是什么? 「🟡 中级」

考察点:JS 面向对象的核心机制。

参考答案

  • 每个对象都有 [[Prototype]]__proto__),指向另一个对象;访问属性时沿原型链向上查找,直到 null。
  • 构造函数有 prototype 属性,new 出来的实例的 __proto__ 指向构造函数的 prototype
  • Object.prototype.__proto__ 是 null,是原型链的终点。
  • instanceof 就是检查原型链上是否存在某个构造函数的 prototype。

追问延伸

  • Object.create(null){} 有什么区别?
  • ES6 class 和原型继承的关系?

Q3: this 的指向规则? 「🟡 中级」

考察点:this 绑定机制,高频易错题。

参考答案

  • 默认绑定:独立调用指向 window(严格模式 undefined)。
  • 隐式绑定:对象方法调用时指向该对象(obj.fn())。
  • 显式绑定call/apply/bind 强制指定 this。
  • new 绑定:构造函数中的 this 指向新创建的实例。
  • 箭头函数:没有自己的 this,继承外层作用域的 this。
  • 优先级:new > 显式 > 隐式 > 默认。

追问延伸

  • setTimeout 里的 this 指向谁?
  • 事件回调里的 this 指向谁?

Q4: 事件循环(Event Loop)是什么? 「🟡 中级」

考察点:JS 异步机制的核心,必问题。

参考答案

  • JS 是单线程的,通过事件循环处理异步任务。
  • 执行顺序:同步代码 → 清空微任务队列(Promise.then、MutationObserver)→ 取一个宏任务执行(setTimeout、setInterval、I/O)→ 再清空微任务 → 循环。
  • 微任务优先级高于宏任务:Promise 回调会在当前宏任务结束后立即执行,不等下一个宏任务。
javascript
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
// 输出:1 4 3 2

追问延伸

  • requestAnimationFrame 是宏任务还是微任务?
  • Node.js 的事件循环和浏览器有什么不同?

Q5: Promise 的状态和链式调用? 「🟢 校招/初级」

考察点:异步编程基础。

参考答案

  • 三种状态:pending → fulfilled / rejected,状态一旦改变不可逆。
  • .then() 返回新的 Promise,实现链式调用;回调的返回值会被 Promise.resolve() 包装。
  • .catch() 捕获前面链路上的错误;.finally() 无论成功失败都执行。
  • 常用组合:Promise.all()(全部成功)、Promise.race()(最快一个)、Promise.allSettled()(全部完成不管成败)。

追问延伸

  • Promise.all 里某个 Promise 失败了怎么拿到其他成功的结果?(allSettled)
  • 怎么手写一个 Promise?

Q6: async/await 的错误处理? 「🟡 中级」

考察点:现代异步编程的规范。

参考答案

  • async 函数返回 Promise;await 暂停执行等待 Promise 完成。
  • 错误处理:
    • try/catch 包裹 await(推荐)。
    • .catch() 链式调用。
    • 封装工具函数返回 [error, data] 元组(Go 风格)。
  • 并发:多个独立的 await 用 Promise.all() 并行执行,避免串行等待。

追问延伸

  • await 在循环里串行执行怎么改成并行?
  • async 函数里的 return 和 throw 分别对应什么?

Q7: 深拷贝怎么实现? 「🟢 校招/初级」

考察点:对象引用与递归。

参考答案

  • JSON.parse(JSON.stringify(obj)):简单但有缺陷(不支持函数、undefined、循环引用、Date/RegExp 等)。
  • 手写递归:处理基本类型、Date、RegExp、Array、Object;用 WeakMap 解决循环引用。
  • 现代方案:structuredClone(obj)(浏览器/Node 原生支持,能处理循环引用)。

追问延伸

  • structuredClone 有什么限制?(不能拷贝函数、DOM 节点)
  • 浅拷贝有哪些实现方式?(Object.assign、展开运算符)