this的指向问题
前言:js中经常会看到this.,在不理解this的时候就会造成this的“滥用”,导致开发过程中需要花费大量的时间查找因为this的指向问题导致的bug。希望通过本文能够让大家理解this,节省大家开发时间。
1、什么是this
this是当前执行代码的环境对象,如果在非严格模式下,总是指向一个对象;如果在严格模式下,可以是任意值。
在不同的情况下this的指向也有所不同,接下来我们看一下几种不同情况下this的指向。
2、不同情况下this的指向
- 全局环境
全局环境中,this指向全局对象(本文只讨论在浏览器环境,不讨论nodejs):
console.log(this === window); // true
- 函数环境
函数环境中,this的值取决于函数被调用的方式,也可以理解为函数由谁调用,this就指向谁:
function f1() {
return this;
}
console.log(f1() === window); // true
f1()调用的时候相当于window.f1(),这里是省略了window。
- 对象方法中
当函数作为对象中的方法被调用时,this是调用该函数的对象:
var user = {
age: 31,
getAge: function() {
return this.age;
}
}
console.log(user.getAge()); // 31
this是在getAge函数中,getAge又是被user调用,所以getAge中的this就指向了user,this.age也就是user.age。
- 原型链中
如果this所在的方法存在于原型链中,那么this也是指向该方法的调用对象:
var util = {
sum: function() {
return this.a + this.b;
}
};
var _util = Object.create(util);
_util.a = 1;
_util.b = 2;
console.log(_util.sum()); // 3
- 构造函数中
当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象:
function userConstructor() {
this.age = 33;
}
var user3 = new userConstructor();
console.log(user3.age); // 33
function userConstructor2() {
this.age = 34;
return {
age: 35
}
}
var user4 = new userConstructor2();
console.log(user4.age); // 35
对于user3.age这个很好理解,而user4中构造函数里直接返回了一个对象,这里如果构造函数中直接返回一个对象,那么通过new关键字创建出来的对象就是return的那个值,所以user.age值为35。
- 箭头函数中
箭头函数中,this与封闭词法环境的this保持一致:
var user4 = {
name: 'tom',
age: 20,
getName() {
console.log(this.name);
},
getAge: () => {
console.log(this.age);
}
}
user4.getName(); // tom
user4.getAge(); // undefined
getName不是用的箭头函数,所以getName中的this指向该函数的调用者user4,this.name也就相当于user4.name;
但是getAge是一个箭头函数,它里面的this指向该函数所在的作用域,根据作用域相关的知识可以知道getAge应该在全局环境中,所以this指向window,这里假设全局环境没有age变量,所以this.age的值就为undefined。
3、如何改变this的指向
虽然this的指向有一定的规则,但是我们也可以主动的修改它的指向,以下三种方法可以修改this:
- call
- apply
- bind
这三种方法可以指定this,具体怎么使用就不再多说,大家可以自行搜索学习。
4、总结
this的指向是前端的一个比较不好理解的知识点,但是一旦理解了this,对我们在平时开发过程中有很大的帮助,能够减小项目出现bug的几率,节省开发时间。