关于箭头函数里的this
先说总结:
- 箭头函数没有自己的this、arguments,箭头函数里的this用的是parent作用域的this。
- 箭头函数里的this是词法作用域,是由代码结构决定的,跟在哪里调用无关,与箭头函数在代码里的位置有关。
- 确定箭头函数里this的指向,可以静态分析代码结构,一直往上找function,如果有,就是最近的function里的this,如果到最外层都没有,就是window。
- 箭头函数的this,一旦确定后是不可更改的。
记住,箭头函数里的this是可以静态分析的,但是函数里的this又完全不一样了
下面开始正文
箭头函数没有自己的this、arguments,箭头函数里的this用的是parent作用域的this。
廖雪峰的文章说,箭头函数里的this是词法作用域。
那么就是由代码结构决定的,跟在哪里调用无关,事实证明也是这样的。
箭头函数出现的位置有两种:
- 在对象里
- 在函数里
箭头函数在对象里
var obj = {
param: 123,
ff : () => console.log(this), // window, strict模式下是undefined
}
因为箭头函数没有自己的this,会去找parent的this,但是对象不构成单独的作用域,没有词法作用域,所以继续往上找parent,就找到了全局作用域。
通过babel编译,发现直接就把this替换成了undefined
// bebal编译后的结果
// void 0就是undefined
"use strict";
var _this = void 0;
var obj = {
param: 123,
ff: function ff() {
return console.log(_this);
}
};
箭头函数在函数里
function test () {
let param = 5656;
let ff = () => console.log(this);
}
箭头函数的this是词法作用域,词法作用域是跟代码结构相关的,那么是可以静态分析的。
因为是词法作用域,那么箭头函数里的this跟在哪里调用无关,与箭头函数在代码里的位置有关。
我们分析一下,箭头函数没有自己的this,会找parent的this,它的parent的是test函数,函数是有作用域的,有词法作用域,所以test里的this就是箭头函数的this。
也就是箭头函数里的this,通过静态分析,会一直往上找function,找到了,就用最近的function里的this,找不到,就用window。
通过babel编译一下,发现箭头函数的this即是test函数里的this:
"use strict";
function test() {
var _this = this;
var param = 5656;
var ff = function ff() {
return console.log(_this); // 这里的this取的是test函数的this
};
}
因为箭头函数和test函数的this是一样的,那么如果test函数里的this变化了,那么箭头函数的this也会跟着变化。比如看这个例子:
let obj = {
param: 123,
ff: function () {
let rr = () => console.log(this);
rr();
}
}
obj.ff(); // obj , 因为这时ff函数里的this是obj对象
let tt = obj.ff;
tt(); // window ,因为这时ff函数里的this是全局对象
这个通过babel编译后的结果是:
"use strict";
var obj = {
param: 123,
ff: function ff() {
var _this = this;
var rr = function rr() {
return console.log(_this);
};
rr();
}
};
obj.ff();
var tt = obj.ff;
tt();
注意,箭头函数的this,一旦确定后是不可更改的
这句的理解是:箭头函数的this一旦确定,就不能更改了,典型的如在setTimeout
函数里用箭头函数。要区分上面的情况,箭头函数rr
的this取的是ff
函数的this,但是ff
函数的this是没有确定的,运行起来后ff
函数的this才确定。
function test () {
return () => console.log(this);
}
let obj = {
aa: 123,
}
let rr = test.call(obj);
setTimeout(rr,1000); // obj ,而不是window 因为箭头函数rr的this已经确定了,后面不能更改
多层嵌套的情况
let obj = {
ff1: function () {
let obj2 = {
ff2: () => console.log(this),
obj3: new Object(() => console.log(this))
};
return obj2;
},
fun1: function (){
return function fun2(){
return function fun3(){
return () => console.log(this);
}
}
}
}
obj.ff1().ff2(); // obj, 取的ff1的this
obj.fun1()()()(); // window,取的fun3的this,由于嵌套函数的this不能继承,所以是window
箭头函数ff2
里的this,向上找parent,obj2是对象没有作用域,继续向上,找到ff1
函数,于是箭头函数ff2
的this就是取ff1
函数的this。obj3的new Object()的传参是箭头函数,里面的this适用的规则也一样,也是一直向上找parent,最后是ff1
函数的this,看babel的转换的代码就知道了。
"use strict";
var obj = {
ff1: function ff1() {
var _this = this;
var obj2 = {
ff2: function ff2() {
return console.log(_this);
},
obj3: new Object(function () {
return console.log(_this); // 取的是ff1的this
})
};
return obj2;
},
fun1: function fun1() {
return function fun2() {
return function fun3() {
var _this2 = this;
return function () {
return console.log(_this2);
};
};
};
}
};
obj.ff1().ff2(); // obj, 取的ff1的this
obj.fun1()()()(); //
总结
- 箭头函数没有自己的this、arguments,箭头函数里的this用的是parent作用域的this。
- 箭头函数里的this是词法作用域,是由代码结构决定的,跟在哪里调用无关,与箭头函数在代码里的位置有关。
- 确定箭头函数里this的指向,是静态分析代码结构,一直往上找function,如果有,就是最近的function里的this,如果到最外层都没有,就是window。
- 箭头函数的this,一旦确定后是不可更改的。
记住,箭头函数里的this是可以静态分析的,但是函数里的this又完全不一样了
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。