ES6箭头函数作用域问题
在看阮一峰老师的ES6入门,在箭头函数那里有点不明白的
箭头函数this绑定定义时的作用域,这个好理解。
后者的
this指向运行时所在的作用域(即全局对象)
这是为什么?运行时不也在Timer()
函数内部?为什么作用域变成全局的了?
function Timer() {this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval(function () {
this.s2++;
}, 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1: 3
// s2: 0
上面代码中,Timer
函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this
绑定定义时所在的作用域(即Timer
函数),后者的this
指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,timer.s1
被更新了 3 次,而timer.s2
一次都没更新。
回答
function () { this.s2++;
}
执行的时候作用域已经是全局作用域啦。
要想s2也改变,可以这样
function Timer() { this.s1 = 0;
this.s2 = 0;
// 箭头函数
setInterval(() => this.s1++, 1000);
// 普通函数
setInterval((function () {
this.s2++;
}).bind(this), 1000);
}
var timer = new Timer();
setTimeout(() => console.log('s1: ', timer.s1), 3100);
setTimeout(() => console.log('s2: ', timer.s2), 3100);
// s1 3
// s2 3
箭头函数没有自己的作用域,其作用域来自其父作用域。如果其父级还是个箭头函数,就继续往上找,直到根作用域为止。
就记住上面加粗的这句话就行了。这是 ES6 的规定,至于为什么这么规定,ECMA 组织没说。
正因如此,箭头函数内部访问 this
、super
、arguments
、new.target
这几个特殊对象,都会去其父作用域里找。
可以看我以前的一个回答,更具体一些:https://segmentfault.com/q/10...
还是要好好理解 运行时作用域
这个概念。
箭头函数理解了,这里跳过不说。
单说这个普通函数。
因为 setInterval
会将回到函数放入 宏任务 中。简单的理解就是它是异步执行的,所以当它执行时, 它的执行环境其实是在 window 上的。
所以回调中的 this.s2 其实就是调用 window.s2
。
timer.s2 声明之后并没有被调用,当然是一次都没更新了。
以上是 ES6箭头函数作用域问题 的全部内容, 来源链接: utcz.com/a/25115.html