1、普通函数
先说说普通函数中的this,各式各样的情况下判断this的指向,可以说是非常刁钻了。判断的时候,只要记住【 this 永远指向调用它的对象,new的时候,指向new出来的对象。】这句话就够了。
看几个例子:
//例1
var obj = {
name: 'latency',
sayName: function(){
console.log('name:',this.name);
}
}
obj.sayName() //name: latency
例1这个例子很好理解,sayName() 方法是 obj 调用的,所以其中的this指向obj。
//例2
var name = 'cheng';
var obj = {
name: 'latency',
sayName: function(){
return function(){
console.log('name:',this.name);
}
}
}
obj.sayName()() //name: cheng
在例2中,打印出来对的this.name不是obj的name,而是window对象的name属性。这是因为sayName()函数中有个闭包,闭包中的this指向调用这个闭包的对象,也就是window对象,写成下面这样可能更好理解:
var fun = obj.sayName();
fun() //name: cheng fun()方法是window对象调用的,其this指向window对象
//例3
var fun = function (a){
this.a = a;
return function(b){
console.log('a+b:', this.a + b);
}
}((function(a,b){return a})(1,2))
fun(3) //a+b: 4
在例3中,首先要明确fun是什么,仔细看代码第7行,我们发现fun是一个立即执行的函数,它的参数也是一个立即执行的函数。
(function(a,b){return a})(1,2) 执行的结果是1,所以fun实际上是下面这样var fun = (function(a){......})(1)
在fun定义的时候,就已经开始执行了,执行结果如下:
var fun = function (a){ //a = 1
this.a = a; //this.a = 1
return function(b){
console.log('a+b:', this.a + b);
}
}(1)
当执行到fun(3)的时候,fun中的闭包函数开始执行,传入参数b=3,由于此时
调用闭包函数的是fun,所以闭包中的this指向fun,从而得出 this.a + b 的值为4。
以上是普通函数中的this,下面来看箭头函数中的this。
2、箭头函数
对于箭头函数的this,也只需要记住一句话【箭头函数没有自己的 this,当在内部使用了 this时,它会指向最近一层作用域内的 this】
上例子,可以把例2改成箭头函数,让它的表现符合我们的预期
//例4
var obj = {
name: 'latency',
sayName: function(){
return () => {
console.log('name:', this.name);
}
}
}
obj.sayName()() //name: latency
在例4中,return的是一个箭头函数,没有把this绑定到自己的内部,使用this时,指向的是上一层的obj。
//例5
var name = 'cheng';
function delay(){
setTimeout(function(){
console.log('name:', this.name);
}, 100)
}
function arrowDelay(){
setTimeout(() => {
console.log('name:', this.name);
}, 100)
}
delay.call({name: 'latency'}) //name: cheng
arrowDelay.call({name: 'latency'}) //name: latency
这个例子就可以很清楚的看出箭头函数和普通函数中this的区别。
根据上面两个例子,我们可以总结出,在函数中需要使用闭包的时候,用箭头函数就很方便了,不需要像以前一样使用hack,类似 var context = this;
接下来把例1改成箭头函数来实现,看看结果:
//例6
var name = 'cheng';
var obj = {
name: 'latency',
sayName: () => {
console.log('name:', this.name)
}
}
obj.sayName() //name: cheng
由于sayName()整个函数就是一个箭头函数,没有自己的this,所以this指向的最近一层作用域内的this,也就是window对象。这种情况下,就不适合用箭头函数来实现了。
再看一个例子
//例7
var obj = {
name: 'latency',
sayName: function(){
return () => {
return () => {
return () => {
console.log("name:", this.name);
};
};
};
}
}
obj.sayName()()()() //name: latency
这个例子可以更好地帮助我们理解【
箭头函数没有自己的 this,当在内部使用了 this时,它会指向最近一层作用域内的 this】这句话。这个例子定义了三个箭头函数,它们都没有绑定this到自己的内部,或者说没有改变this的指向,所以this始终指向obj。