this 的作用是 指向 当前调用者(即 this 的指向并非固定的)。
由于this的指向不定,容易引发bug,举个例子:
class Test{
constructor(){
this.value = 1;
}
fn() {
console.log(this.value);
}
}
var ins = new Test(); //new出来的实例
ins.fn(); //输出 1(因为this指向的当前调用者是ins,ins.value为 1)
var fun = ins.fn;
fun(); //报错(因为严格模式下,执行fun时并无调用者,所以this指向为undefined)
window.fun(); //输出undefined(因为this指向当前调用者window,而window中并无value)
如果想要执行fun时,能正确输出 1,有三个方法:
方法1:使用bind进行绑定。比如
class Test{
constructor(){
this.value = 1;
this.fn = this.fn.bind(this); //将fn中的this绑定为 new出来的实例
}
fn() {
console.log(this.value);
}
}
var ins = new Test(); //new出来的实例
var fun = ins.fn;
fun(); //输出 1(因为fn中的this 已被绑定为ins实例)
window.fun(); //输出 1(var声明的 fun 和 window.fun 其实是一样的)
方法2:提前用一个变量将this的值存起来,并用该变量替代this。比如
var that; //随便声明一个变量
class Test{
constructor(){
that = this; //此时的this指向new出来的实例,同时存于that中
this.value = 1;
}
fn() {
console.log(that.value); //用that替代this
}
}
var ins = new Test(); //new出来的实例
var fun = ins.fn;
fun(); //输出 1(因为that会一直指向ins实例)
window.fun(); //输出 1(var声明的 fun 和 window.fun 其实是一样的)
方法3:使用箭头函数。比如
class Test{
constructor(){
this.value = 1;
}
fn = () => { //使用箭头函数
console.log(this.value);
}
}
var ins = new Test(); //new出来的实例
var fun = ins.fn;
fun(); //输出 1(因为此时的this指向上一层的this,即ins实例)
window.fun(); //输出 1(var声明的 fun 和 window.fun 其实是一样的)
箭头函数的作用:
1.语法糖,写起来更简洁
2.不动态绑定 this 的指向
注意:第2点是重点,意味着?this 与当前调用者没有关系了。那么 this 此时会沿着作用域链,向上一层找最近的 this(最外层的 this 则为window)。
?下图为最外层的 this:
|