参考博文:嗨,你真的懂this吗?
箭头函数是ES6中的新增特性,他没有自己的this
,其this
指向从外层代码库继承。
使用箭头函数时要注意一下几点:
- 箭头函数不能用作构造函数,用的话会抛出一个错误
- 无法使用
arguments
参数,如果要用的话就用rest
- 无法使用
yield
命令,所以箭头函数无法用作Generator
函数 - 因为没有自己的
this
,所以没法通过bind
、call
、apply
来改变this
指向 - 但是这不代表箭头函数的
this
指向是静态的,我们可以通过改变它外层代码库的this
指向来控制 - 箭头函数的
this
从外层代码库继承,所以箭头函数的this
是在定义的时候就绑定好了的,而普通函数是在调用的时候确定this
指向 - 字面量对象中直接定义的箭头函数的
this
不绑定该对象,而是往外找一层,最简单的情况是绑定到window
PS: 实际开发环境中,React
可以使用箭头函数解决一个经典问题,这里不细说了。
给一个例子看一下箭头函数的实际情况:
const obj = {
fun1: function () {
console.log(this);
return () => {
console.log(this);
}
},
fun2: function () {
return function () {
console.log(this);
return () => {
console.log(this);
}
}
},
fun3: () => {
console.log(this);
}
}
let f1 = obj.fun1(); // obj
f1() // obj
let f2 = obj.fun2();
let f2_2 = f2(); // window
f2_2() // window
obj.fun3(); // window
针对每行输出的分析:
let f1 = obj.fun1() // obj
这里明显进行的是隐式绑定,fun1
的this
指向obj
f1() // obj
这里执行了上一行返回出来的箭头函数,我们分析上一层代码库的this
指向obj
,所以直接继承,箭头函数this
指向obj
let f2 = obj.fun2()
fun2
第一层执行的时候没有打印代码,而是返回了一个函数出来,赋值给f2
,并且这里发生了绑定丢失,this
指向由原来的obj
指向了window
(发生了赋值)let f2_2 = f2() // window
f2()
执行了,打印出了改绑后的this
——window
,然后将箭头函数返回出来,赋值给f2_2
f2_2() // window
执行打印出window
,刚才的外层代码的this
不是指向了window
吗,所以这里就继承了window
作为this
obj.fun3() // window
在字面量中直接定义的箭头函数无法继承该对象的this
,而是往外再找一层,就找到了window
,因为字面量对象无法形成自己的一层作用域,但是构造函数可以哦。
那我们怎么操纵箭头函数的this
指向呢:
答案是修改外层代码库的this
指向,在箭头函数定义之前就给this
修改方向即可。
在以上代码的基础上:
let fun4 = f2.bind(obj)() // obj
fun4() // obj
我们发现修改的是第二层方法的this
指向,并且箭头函数也继承了下来。
fun2: function () {
return function () { // 我们修改的是这里的this
console.log(this);
return () => { // 然后这里定义的时候就继承啦
console.log(this);
}
}
},
芜湖
如果绑定丢失或隐式绑定等不明白可以看上一篇博客。