JavaScript三段代码差异解析:变量作用域与this指向问题
全局变量、局部变量与this指向的核心差异解析
先明确两个基础规则:
- 函数内部访问变量时,局部变量优先级高于全局变量,所以三段代码中第二个
console.log(counter)都会输出局部的50,这部分逻辑一致。 - 差异核心在于
this.counter的取值,完全由函数调用时的this指向决定。
第一段代码:普通函数直接调用
var counter = 3; function example() { let counter = 50; console.log(this.counter); console.log(counter); }; example();
输出:
Undefined 50
- 普通函数直接调用时,非严格模式下
this指向全局对象(浏览器为window,Node.js为global);但如果代码运行在模块环境(ES模块或Node.js模块)中,用var声明的变量会被限制在模块作用域内,不会挂载到全局对象上,因此this.counter找不到对应属性,输出undefined。 - 若在普通浏览器全局环境(非模块)中,
var counter = 3会自动挂载到window,此时this.counter会输出3——你的输出为undefined,说明代码运行在模块环境中。
第二段代码:用call绑定原始值
var counter = 3; var example = function() { let counter = 50; console.log(this.counter); console.log(counter); } example.call(counter);
输出:
Undefined 50
call方法的作用是绑定函数执行时的this,但你传入的counter是原始值3(数字类型)。JavaScript会自动把原始值包装成对应的包装对象(这里是Number对象),但Number对象本身并没有counter属性,因此this.counter输出undefined。- 函数内部的局部
counter依然优先,所以第二个输出还是50。
第三段代码:用call绑定自定义对象
var counter = 3; var example = function() { let counter = 50; console.log(this.counter); console.log(counter); } example.call({counter});
输出:
3 50
- 这里的
({counter})是ES6对象字面量的简写语法,等同于{counter: counter}——意思是创建一个新对象,其中counter属性的取值等于全局变量counter的值(也就是3)。 - 用
call把这个自定义对象绑定为函数的this,此时this.counter访问的就是该对象的counter属性,因此输出3;局部变量counter依然优先,第二个输出为50。
为什么前两段拿不到全局的3?
- 第一段:模块环境下全局变量不会挂载到全局对象,而直接调用函数时
this指向全局对象,因此无法通过this.counter访问全局变量。 - 第二段:绑定的原始值被包装成包装对象后,该对象没有
counter属性,自然无法获取全局的3。
内容的提问来源于stack exchange,提问作者Ahmed Tareque
相关产品推荐
相关产品推荐

