各层级定义var变量得到非预期结果,为何JS代码输出是4而非3
JavaScript代码输出4而非3的原因
var x=4, obj={ x: 3, bar:function(){ var x = 2; setTimeout(function(){ var x=1; console.log(this.x); },1000); } } obj.bar();
输出结果为4的核心原因是普通函数作为setTimeout回调时的默认this绑定规则,和局部变量作用域无关,具体逻辑拆解如下:
- 非严格模式下,setTimeout的普通函数回调执行时,
this默认绑定到全局对象:浏览器环境为window,Node.js环境为globalThis。 - 代码执行逻辑梳理:
- 顶层用
var声明的x=4会自动成为全局对象的属性,即window.x = 4。 obj.bar()调用时,bar函数内部的this确实指向obj,此时this.x为3,但这个this不会自动传递给内部的setTimeout回调。- setTimeout的回调是独立执行的普通函数,它内部的
this指向全局对象,因此console.log(this.x)读取的是全局对象的x属性,也就是4。 bar函数内的var x=2、回调内的var x=1都是函数局部作用域的变量,和this.x完全不相关:this.x读取的是this绑定对象的属性,不是当前作用域的局部变量。
- 顶层用
- 如果要让输出为3,只要修改回调的this绑定即可,常见方案两种:
- 改用箭头函数作为回调,箭头函数会继承外层执行上下文的
this:
setTimeout(() => { var x=1; console.log(this.x); // 继承bar函数的this指向obj,输出3 }, 1000);- 用
bind手动绑定回调的this指向:
setTimeout(function(){ var x=1; console.log(this.x); // 手动绑定this为obj,输出3 }.bind(obj), 1000); - 改用箭头函数作为回调,箭头函数会继承外层执行上下文的
内容的提问来源于stack exchange,提问作者Satyam Kumar
相关产品推荐
相关产品推荐

