JS之 this 与箭头函数

362 阅读1分钟

原文出处:【建议👍】再来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