觉得自己的 JavaScript 功底还不错?那来试试这道复杂的面试题吧!
下面是一段代码,请分析每一行的输出,并解释其背后的原因。
问题描述
以下是代码,预测输出并说明逻辑:
function Foo() {
this.value = 42;
}
Foo.prototype.getValue = function() {
return this.value;
};
const obj1 = new Foo();
const obj2 = {
value: 24,
getValue: obj1.getValue
};
console.log(obj1.getValue()); // A
console.log(obj2.getValue()); // B
setTimeout(function() {
console.log(obj1.getValue()); // C
obj2.value = 100;
console.log(obj2.getValue()); // D
}, 0);
Promise.resolve().then(() => {
obj1.value = 84;
console.log(obj1.getValue()); // E
});
console.log(obj1.getValue()); // F分析与输出
A:obj1.getValue()
console.log(obj1.getValue()); // A解释:
obj1是Foo的实例,obj1.getValue()调用的是原型上的getValue方法。- 方法中的
this指向obj1,返回this.value。 obj1.value初始化为42,因此输出:
输出:42
B:obj2.getValue()
console.log(obj2.getValue()); // B解释:
obj2.getValue是直接引用了obj1.getValue,但调用时通过obj2.getValue()。- 在 JavaScript 中,
this的绑定依赖调用的对象。在这里,this指向obj2。 obj2.value为24,因此输出:
输出:24
F:同步执行的 obj1.getValue()
console.log(obj1.getValue()); // F解释:
- 此处仍是
obj1.getValue()的调用,且obj1.value尚未被异步代码修改。 - 因此输出和 A 一样,为:
输出:42
E:Promise 中的 obj1.getValue()
Promise.resolve().then(() => {
obj1.value = 84;
console.log(obj1.getValue()); // E
});解释:
Promise的回调是微任务,在同步代码执行完后立即执行。- 回调中将
obj1.value修改为84,随后调用obj1.getValue()。 - 因此此处返回的是更新后的值:
输出:84
C:setTimeout 中的 obj1.getValue()
setTimeout(function() {
console.log(obj1.getValue()); // C
obj2.value = 100;
console.log(obj2.getValue()); // D
}, 0);解释:
setTimeout的回调是宏任务,在同步代码和微任务都执行完后才会执行。- 此时,
obj1.value已被微任务修改为84,调用obj1.getValue()返回的是修改后的值:
输出:84
D:setTimeout 中的 obj2.getValue()
console.log(obj2.getValue()); // D解释:
- 在
setTimeout的回调中,obj2.value被修改为100。 - 调用
obj2.getValue(),this仍指向obj2,因此返回的是更新后的值:
输出:100
完整输出顺序
- A:
42 - B:
24 - F:
42 - E:
84 - C:
84 - D:
100
背后的知识点
这道题涉及了 JavaScript 中多个高级概念,是对语言机制的一次全面考察:
原型继承:
obj1调用了Foo构造函数,通过原型链继承了getValue方法。
动态绑定的
this:this的指向取决于函数的调用方式,而不是定义时的上下文。
事件循环与任务队列:
- 同步代码优先执行,
Promise的微任务队列紧随其后,而setTimeout的回调则在最后的宏任务队列中执行。
- 同步代码优先执行,
值的动态修改:
- 不同任务(同步、微任务、宏任务)对变量的修改会影响之后的结果。
总结
这道题表面看起来是简单的输出预测,但实际上需要对 JavaScript 的事件循环、this 绑定规则和原型链有全面的理解。通过这类问题的深入分析,不仅可以提升代码阅读能力,也能更自信地处理实际开发中的复杂场景。
首发于公众号 大迁世界,欢迎关注。📝 每周一篇实用的前端文章 🛠️ 分享值得关注的开发工具 ❓ 有疑问?我来回答
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用。你还可以使用@来通知其他用户。