原文出处:【建议👍】再来40道this面试题酸爽继续(1.2w字用手整理) - 掘金 (juejin.cn)
ES5时期
var obj1 = { a: 1 }
var obj2 = {
a: 2,
foo1: function () { console.log(this.a) },
foo2: function () {
setTimeout(function () {
console.log(this)
console.log(this.a)
}, 0) }
}
var a = 3
obj2.foo1()
obj2.foo2()
//
2
Window{...}
3
众所周知,this 的指向在调用时被确定
在调用 foo1 时,显然函数中的 this 为 obj2,所以结果为 2
而在调用 foo2 时,其中的 'this' 由计时器打印,那为什么会是 window 呢
这是因为计时器属于异步任务,引擎遇到异步任务,不会立即执行,而是存放到任务队列中,当主执行栈任务结束后,异步任务才会被执行
哪怕你设定的秒数为 0,也仅表示至快 0 秒执行,大多数情况下都不完全准确
所以计时器的回调是由 window 帮我们调用,那么其中的 this 即是 window
ES6新时期
出现了箭头函数,箭头函数的 this 继承上一层作用域的 this,也就是说,this 在定义时被确定,让我们改写上例
var obj1 = { a: 1 }
var obj2 = {
a: 2,
foo1: () => { console.log(this.a) },
foo2: function () {
// 此处 this 为 obj2
setTimeout(()=> {
console.log(this)
console.log(this.a)
}, 0) }
}
var a = 3
obj2.foo1()
obj2.foo2()
//
3
{a: 2, foo1: ƒ, foo2: ƒ}
2
可以看到,foo1 打印出了全局的属性,此处的箭头函数继承上一层作用域中的 this ,即是 window
而 foo2 函数中的 this 为 obj2,箭头函数自然将 this 锁定为 obj2