JavaScript普通函数返回的箭头函数为何输出88而非undefined?
箭头函数this绑定规则解析
核心底层机制
- 普通函数的this值完全由调用时刻的上下文决定,和定义位置无关。常见绑定规则包括:全局调用时绑定全局对象(严格模式下为undefined)、对象属性方法调用时绑定当前调用的上下文对象、new调用时绑定新建的实例对象、call/apply/bind显式指定绑定对象。
- 箭头函数不存在自身的this构造,它的this值在函数定义时就从外层词法作用域永久继承,后续无论用什么形式调用箭头函数,都无法修改这个继承来的this,也不能通过call/apply/bind重定向指向。
当前代码的完整执行路径
- 执行
let t = obj.d()时,采用obj.方法名()的形式调用普通函数d。按照隐式绑定规则,d函数本次执行的内部this会直接绑定到调用上下文obj。 - d函数内部返回的匿名箭头函数,定义在d的函数执行上下文中。因为箭头函数没有自己的this,它会沿作用域链向上查找最近的this绑定值,也就是d函数执行时绑定的、指向obj的this。
- 这个箭头函数被赋值给全局变量t后,再执行
t()时,虽然是全局作用域下的函数调用形式,但箭头函数不会根据当前调用方式重新绑定this,只会直接使用定义时继承来的this(指向obj)。此时访问this.a本质是读取obj对象的a属性值"88",因此最终控制台输出88,而非undefined。
易混淆场景对照
- 如果将d函数内返回的箭头函数替换为普通函数,即
return function() { console.log(this.a) },t调用时的this会按照全局调用规则绑定为全局对象/严格模式下的undefined,此时输出才是undefined,和箭头函数的行为有本质区别。 - 代码中定义的
ob对象没有参与本次执行流程:如果将d的调用上下文切换为ob,比如执行let t = obj.d.call(ob),那么d函数执行时的this会绑定为ob,内部箭头函数继承的this也会变为ob,此时执行t()就会输出99。 - 对比obj中的c箭头函数:c是直接在全局作用域下定义的箭头函数,它的外层作用域是全局上下文,因此c内部的this绑定到全局对象,调用c()时不会读取obj的a属性。
内容的提问来源于stack exchange,提问作者gANDALF
相关产品推荐
相关产品推荐

