在箭头函数中,this由词法/静态作用域设置(set lexically)。它被设置为包含它的execution context的this,并且不再被调用方式影响(call/apply/bind)。
由于箭头函数中的this是被静态作用域设置,即函数被定义的时候就决定了一切,所以呢,就算怎么改变this的指向,它还是会指向原来的对象,即全局对象。
普通函数this,是在执行的时候确定this指向,简单粗暴的就认为,执行时候.前面的就是this
1 window.val =1;
2 var obj ={
3 val :3 ,
4 fn:function(){
5 this.val*=3;
6 val*=2;
7 console.log(val);
8 console.log(this.val)
9 }
10 }
11 obj.fn();
12 var r = obj.fn;
13 r(); //注意r是代表fn函数,这里就是fn函数执行,执行前面看.,他前面没.,那么它执行的时候就是window.r(),所以this就是window
箭头函数本身没有this指向,在定义的时候就以外层作用域(说准确点就是外层函数作用域)的this为自己的this(直到找到window)。
var obj ={
fn:function(){
console.log(this)
},
say:function(){
setTimeout(()=>{
console.log(this)
})
}
}
obj.fn();
obj.say(); //自己没有this指向,定义的时候找外层作用域,外层就是say函数,say函数作用域的this就是箭头函数的this,say函数执行的时候.前面的是obj,那么say函数中的this
//就是obj,那么作为箭头函数的外层,箭头函数的this就是say函数的this,即obj
箭头函数与普通函数对比:
//普通函数
var obj = {
a: function() { console.log(this) },
b: {
c: function() {console.log(this)}
}
}
obj.a()
obj.b.c() //普通函数看执行的地方,执行的c函数,那就看c函数前的.,.前面的就是this,那自然this就是obj.b
//有箭头函数
1 var obj = {
2 a: function() { console.log(this) },
3 b: {
4 c: ()=> {console.log(this)}
5 }
6 }
7 obj.a()
8 obj.b.c() // 箭头函数不看执行的地方,要看定义的地方,外层函数作用域的this就是他的this,由于外层是b对象,b对象的中的this就是window,所以箭头函数随外面的this就是window
var obj = {
a: function() { console.log(this) },
b: function(){
return ()=> {console.log(this)}
}
}
obj.a()
obj.b()() //因为是箭头函数,所以定义的时候要找外层函数作用域,外层函数作用域呢,就是b函数,在obj.b()也就是b函数执行的时候,b函数内部的this就是obj,因为.前面的就是obj,
//那么b函数作为箭头函数的外层作用域,箭头函数的this就是b函数执行时候的this
var obj = {
a: function() { console.log(this) },
b: function(){
return function() {console.log(this)}
}
}
obj.a()
obj.b()() //因为没有箭头函数,所以看执行时候.前面的,obj.b()就是最后一步执行所对应的.前面的,就是return了一个匿名函数,那么匿名函数的this就是window
var obj = {
a: function() { console.log(this) },
b: ()=>{
return ()=> {console.log(this)}
}
}
obj.a()
obj.b()() //箭头函数外层外层函数作用域又是一个箭头函数,外层没有this,指向window,再往上找还是window,那么内层这个就也指向window
var obj = {
a: function() { console.log(this) },
b:function(){
return ()=>{
return ()=> {console.log(this)}
}
},
}
obj.a()
obj.b()()(); //往上一级级的找,找到了obj.b函数的作用域,指向obj,所以箭头函数的this指向外层的obj