我之前的错误理解是:
-
箭头函数的 this 在编译时确定,继承最近一层函数的 this(或者是最后的全局 this)
-
而大多数情况下,最近一层的函数是非箭头函数,明知它的 this 是在调用时确定的,所以我错误地理解为以定义时的结构为标准(例如对下面的例子,我直接把 this 认为是 obj1.getThisGetter() 调用时的 this)
-
根据上面的思路,也可以得到一个箭头函数 this 指向的特点是它的 “不变性”
下面是案例,可以先自己做一下,别翻太快,答案就在下面
const obj1 = {
name: 'obj1',
getThisGetter() {
return () => this
}
}
const obj2 = {
name: 'obj2'
}
const thisGetter1 = obj1.getThisGetter()
const thisGetter2 = obj1.getThisGetter.call(obj2)
const this1 = thisGetter1()
const this2 = thisGetter2()
console.log(this1.name)
console.log(this2.name)
// 下面就是答案了!!!
// 不要翻太远!!!
// 最后警告!!!
根据这个错误的思路,可以爽快地得到输出结果是:obj1 obj1,
但实际输出是:obj1 obj2
“不是说 this 在编译时确定吗,怎么会变呢?”
实际上:
-
箭头函数没有自己的 this,它通过闭包继承外层作用域的 this:
箭头函数中获取 this 和通过闭包获取其他的外部参数是同一个操作 -
闭包的词法作用域在编译时确定,但这个作用域的 this 值是在执行时确定的:
如果外层作用域不执行(例子中的 getThisGetter 不调用),内部箭头函数的 this 就没有意义(定义时) -
因此箭头函数的 this 最终取决于外层函数的调用方式(或其他作用域)
所以例子中:
const thisGetter1 = obj1.getThisGetter()
const thisGetter2 = obj1.getThisGetter.call(obj2)
这里 getThisGetter 两次执行的时候产生两个不同的包含箭头函数的上下文,他们是相互独立的,并且各自的 this 在这时候被确定
所以说箭头函数的 this 不是编译时确定的,也是运行时确定的