ES6箭头函数与传统函数的this指向及作用域差异疑问
核心知识点误区澄清
你混淆了「普通变量的词法作用域查找规则」和「普通函数this的绑定规则」,二者是完全独立的两套逻辑:
- 普通变量的查找确实遵循词法作用域,按声明位置的嵌套关系从内到外查找
- 普通函数的
this是动态绑定,和声明位置完全无关,仅由函数被调用的方式决定
普通函数this的4种绑定规则
普通函数的this绑定优先级从高到低如下:
- new绑定:函数被
new调用时,this绑定到新创建的实例对象 - 显式绑定:通过
call/apply/bind手动指定this时,this绑定到传入的对象 - 隐式绑定:函数作为对象的方法被调用时(形如
obj.func()),this绑定到前面的对象obj - 默认绑定:以上三种都不满足的「独立函数调用」场景,非严格模式下
this绑定到全局对象(浏览器环境为window,Node环境为globalThis),严格模式下为undefined
针对你给出的示例逐一解释
示例3的问题根源
你示例中的namedFn()就是典型的独立调用,没有前缀对象、没有手动指定this、也不是new调用,直接触发默认绑定,非严格模式下this就是window。而全局window上没有定义count属性,所以this.count输出undefined。
哪怕namedFn声明在doSomethingLater内部,也不会影响this的绑定结果,因为普通函数this和声明位置无关。
MDN传统函数示例的问题根源
setTimeout传入的普通函数回调,在执行时是JS引擎独立调用的,同样触发默认绑定,this指向window。初始时window.count为undefined,执行this.count++后结果为NaN,和示例3本质是同一个原因。
箭头函数的特殊规则
箭头函数不存在自己的this,它的this完全遵循词法作用域规则,继承自外层作用域的this,所以才会出现你看到的和普通函数完全不同的表现。
简单修改方案
如果想让示例3中namedFn的this指向外层的obj,可以用以下任意一种方式修改:
- 用
bind显式绑定this:namedFn.bind(this)()(doSomethingLater是作为obj的方法调用的,内部this指向obj) - 把
namedFn改成箭头函数:const namedFn = () => {console.log(this.count)},继承外层作用域的this - 调用时用
call显式传入this:namedFn.call(this)
内容的提问来源于stack exchange,提问作者Angela P
相关产品推荐
相关产品推荐

