JavaScript中设置函数自身属性为何不影响函数内部this取值
核心原因
这是JavaScript中this绑定规则和函数对象基础特性导致的:你给step函数对象设置的counter属性,和函数内部this访问的counter根本不在同一个对象上,自然不会互相影响。
具体逻辑拆解
- 首先记一个非严格模式下最基础的
this规则:如果直接用函数名()这种无上下文的裸调用方式执行普通函数,函数内部的this默认指向全局对象——浏览器环境对应window,Node.js环境对应globalThis。 - 其次要明确:JavaScript里函数本身是一等公民,属于特殊的对象,你写
step.counter = 10,本质是给step这个函数对象本身添加自有属性,这个属性存储在函数对象自身的内存空间里,和全局对象没有关联。 - 回到你的代码,不管你有没有提前给
step设置counter属性,step()执行时this.counter读写的都是全局对象上的counter,根本不会触碰step函数对象自身的counter属性。
第二段代码的实际执行流程
- 声明
step函数,此时全局对象、step函数对象上都不存在counter属性 - 执行
step.counter = 10:仅给step函数对象添加值为10的counter属性,全局对象上依然没有该属性 - 第一次调用
step():- 函数内
this指向全局对象,判断!this.counter为真(全局对象上counter值为undefined,转布尔值为false) - 给全局对象挂载
counter属性,赋值为0 - 执行后置自增
return this.counter++,返回0,执行完成后全局对象上的counter变为1
- 函数内
- 后续两次调用
step(),都是在操作全局对象上的counter,依次返回1、2,全程没有访问过step函数对象上值为10的counter,因此输出和未设置该属性时完全一致。
补充验证
如果你希望函数内部访问到自身的counter属性,只需要手动把this绑定到step函数对象即可,比如用call方法:
function step() { if (!this.counter) this.counter = 0; return this.counter++; } step.counter = 10; console.log(step.call(step)); // 输出10 console.log(step.call(step)); // 输出11 console.log(step.call(step)); // 输出12
额外说明:如果代码运行在严格模式下,裸调用普通函数时this为undefined,此时访问this.counter会直接抛出类型错误,不会出现隐式绑定全局对象的行为,也能帮你更早发现这类指向问题。
内容的提问来源于stack exchange,提问作者kalkronline
相关产品推荐
相关产品推荐

