this 补充
任何足够先进的技术都和魔法无异
普通函数和箭头函数下的 this
代码语言:javascript复制var obj = {
id: "awesome",
cool: function coolFn() {
console.log(this.id);
},
};
var id = "not awesome";
obj.cool();
setTimeout(obj.cool, 100); // not awesome
我们可以看到,我们预期这里会输出awesome
,结果打印结果显示我们丢失了this
的绑定,解决这个问题的办法有很多种,最常见的就是 var self = this
self
代码语言:javascript复制var obj = {
count: 0,
cool: function coolFn() {
var self = this;
if (self.count < 1) {
setTimeout(function timer() {
self.count ;
console.log("awesome?");
}, 100);
}
},
};
obj.cool(); // awesome
用var self = this
这种解决方案可以圆满解决理解和正确使用this
绑定的问题,并且没有把问题复杂化,它使用的是我们常见的工具:词法作用域
this
只是一个可以通过词法作用域和闭包进行引用的标识符,不关心this
绑定的过程发生了什么
人们不喜欢写冗长的东西,尤其是一遍一遍地写。因此ES6
的一个初衷就是帮助人们减少重复的场景,事实上包括修复某些习惯用法的问题,this
就是其中一个。
箭头函数下的 this
ES6
中的箭头函数引入了一个叫作this
词法的行为:
var obj = {
count: 0,
cool: function coolFn() {
if(this.count < 1) {
setTimeout(() => {
this.count ;
console.log('awesome');
}, 100);
}
}
}
简单来说,箭头函数在涉及this
绑定时的行为和普通函数的行为完全不一样,它完全摒弃了所有普通 this
的绑定规则,取而代之的是用当前的词法作用域覆盖了this
本来的值。
因此,这个代码片段中的箭头函数并非是以某种不可预测的方式同所属的this
进行了解绑定,而只是继承了 cool 函数的 this
绑定(因此调用它不会出错)
除了可以少写点代码,箭头函数将程序员们经常犯的一个错误给标准化了,也就是混淆了this
绑定规则和词法作用域规则。
箭头函数的弊端
- 我们为什么要自找麻烦使用
this
风格的代码模式呢?把它和词法作用域结合在一起非常让人头疼。在代码中使用两种风格的其中一种是非常自然的事情,但是不要将两种风格混在一起使用 - 箭头函数是匿名而非具名的,具体的弊端可见作用域那块的详细描述
更好的办法
代码语言:javascript复制var obj = {
count: 0,
cool: function coolFn() {
if(this.count < 1) {
setTimeout(function timer() {
this.count ;
console.log('more awesome');
}.bind(this), 100);
}
}
}