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的时候 发现fn是箭头函数,立即把this绑定为ins
var fun = ins.fn;
fun(); //输出 1(因为this早已被绑定为ins实例)
window.fun(); //输出 1(var声明的 fun 和 window.fun 其实是一样的)
箭头函数的作用:
1.语法糖,写起来更简洁
2.在函数声明定义的时候,this就被指定好了;而普通函数是在执行的时候,才动态指定this
注意:在new出实例的时候,this才会被绑定为该实例,而不是在声明class的时候绑定。因为在class未实例化之前,其内部的属性和方法还不算已被声明(如果已声明则可以调用了)。
下图为全局作用域下的 this: