如何通过JavaScript面试:高级水平热门问题
\n\n高级JavaScript开发人员或Node.js工程师职位的面试,不仅仅是检查语法。面试官希望看到你对语言的深刻理解:事件循环是如何工作的,this上下文到底是什么,以及如何避免处理异步时的“回调地狱”。在本文中,我们将分析在高级水平面试中最常见和最棘手的问题。准备好不仅仅是阅读答案,而是要理解其机制。
1. 事件循环、调用栈和微任务(微任务 vs 宏任务)
\n\n这可能是Node.js面试中最常见的一个模块。问题通常是:“这段代码会输出什么,顺序是什么?”
\n\nconsole.log('1');\n\nsetTimeout(() => console.log('2'), 0);\n\nPromise.resolve().then(() => console.log('3'));\n\nprocess.nextTick(() => console.log('4'));\n\nconsole.log('5');\n\n正确答案: 1, 5, 4, 3, 2。
\n\n解析:
\n- \n
- 同步代码 (1, 5) 首先执行。 \n
- process.nextTick() — 优先级最高的微任务。它在当前操作之后立即执行,但在任何其他微任务(Promise)和宏任务(setTimeout)之前。 \n
- Promise.then() — 也是微任务,但其优先级低于
nextTick。 \n - setTimeout(cb, 0) — 宏任务。它仅在调用栈和所有微任务(所有
nextTick和Promise)完全清空后执行。 \n
如何正确回答: 解释Node.js有事件循环阶段。微任务(process.nextTick 和 Promise)在阶段之间处理。宏任务(setTimeout、setInterval、I/O)在阶段内部处理。nextTick 是一个非标准但非常重要的队列,如果递归使用它,可能会阻塞事件循环。
2. this 上下文及其“丢失”
\n\n问题:“this 在JavaScript中是如何工作的?请举一个 this 丢失的例子,并说明如何修复。”
高级水平意味着你需要知道4条规则:
\n- \n
- new 绑定 — 当通过
new调用函数时,this指向新创建的对象。 \n - 显式绑定 —
call、apply、bind。 \n - 隐式绑定 — 当函数作为对象的方法调用时(obj.method())。 \n
- 默认绑定 — 全局对象(Node.js中的
global,浏览器中的window)或严格模式下的undefined。 \n
上下文丢失的例子:
\nconst user = {\n name: 'Alice',\n greet() {\n console.log(`Hello, ${this.name}`);\n }\n};\n\nconst greetFn = user.greet;\ngreetFn(); // Hello, undefined\n\n为什么? 我们将方法赋值给了一个变量。现在 greetFn() 在没有对象上下文(user)的情况下被调用。this 绑定到了全局对象(或严格模式下的 undefined)。
如何修复:
\n- \n
- 使用
bind:const greetFn = user.greet.bind(user);\n - 使用箭头函数(它没有自己的
this,而是从外部词法环境获取)。 \n - 通过
call/apply调用:greetFn.call(user)。 \n
附加问题: “如果 user.greet 被传递给 setTimeout 会发生什么?” — 同样的丢失效果。通过 bind 或在回调中使用箭头函数来修复。