阮一峰es6中说到:
箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象,箭头函数中没有自己的this的,而箭头函数会默认使用父级的this。
而普通的this:总是代表它的直接调用者,没找到直接调用者,则this指的是 window(匿名函数,定时器中的函数,由于没有默认的宿主对象,所以默认this指向window)。
那么怎么找到箭头函数定义是时所在的对象?
我们先来举个栗子
let aLi = document.getElementsByTagName('li');
for(var i=0; i<aLi.length; i++){
aLi[i].onclick = function(){
setTimeout(function(){
console.log(this); //输出window
},1000);
}
}
输出结果为window,原因是这里是window.setTimeout,所以this指向window。
那么如果用箭头函数的方式来实现会输出什么?
let aLi = document.getElementsByTagName('li');
for(var i=0; i<aLi.length; i++){
aLi[i].onclick = function(){
//这里是外部作用域,this指向点击的dom元素
setTimeout(() => {
console.log(this); //this指向外部作用域中的this
},1000);
}
}
输出结果是点击的dom元素,原因是箭头函数中的this指向父作用域,要沿当前作用域向上找,找到点击事件中,在点击事件中this指向当前点击的dom元素,所以输出的是点击的dom元素。
如果还是感觉有点懵... , 看看下边的这个例子:
//这是父作用域,this指向window
let person1 = {
name:'lisi',
age:10,
//注意这里并没有this
say:() => {
console.log(this);//输出window
}
}
person1.say();
如果刚才有点懵,那么看完这个我觉得你会更懵......,
为什么会输出window,其实原因很简单,day方法中的this因为在箭头函数中,所以指向父作用域中,父作用域就是最外层作用域,父作用域中的this指向window,所以输出window。
有的同学可能会想say方法中的父作用域怎么不是对象person1 = {} 中我标记‘//注意这里并没有this’的位置,因为这里是个对象,对象中有属性,方法,但并没有this。
接下来我们把它改成定时器使用箭头函数的方式:
let person1 = {
name:'lisi',
age:10,
say:function(){
//这里是外部作用域 ,this指向person1,即箭头函数中的this指向person1
setTimeout(() => {
console.log(this); //this指向外部作用域中this
});
}
}
person1.say(); //输出person1对象
这个例子中,定时器箭头函数中的this指向外部作用域,即指向say方法中,say方法中this指向person1对象,所以输出person1对象。
那么如果我把say方法也改成箭头函数:
//这里是外部作用域 this指向window,即最终console中的this指向window
let person1 = {
name:'lisi',
age:10,
say:()=>{
//这里是外部作用域,因为本身又是箭头函数,继续向上找
setTimeout(() => {
console.log(this); //this指向外部作用域中this
});
}
}
person1.say(); //输出window
这个例子中定时器箭头函数中的this向上say方法中的this,但由于say方法中也是箭头函数,所以say方法中的this还要继续向上找,即找到了最外层,所以最后指向window。
总结:箭头函数中this,首先到它的父作用域找,如果父作用域还是箭头函数,那么接着向上找,直到找到我们要的this指向。