众所周知,ES6的箭头函数提供了一种更加简洁的函数书写方式,但同样的,箭头函数也缺少了一些基本函数所具有的内部弱属性,比如this。虽然没有自己的this,但是箭头函数在创建的时候会绑定一个this,且不可改变,后面有需要用到的地方就用这个this。那么,箭头函数绑定的this是哪儿来的呢?带着这个问题,我写了几个函数,终于搞懂了箭头函数的this的指向问题。
1、函数执行的时候创建箭头函数
1.1、直接调用
function a() {
const test = () => console.log(this); // window
test();
}
// test也就是箭头函数是在a函数执行的时候创建,a函数执行的时候this指向是window,所以箭头函数的this是Window
a() // Window
1.2、间接调用
const b = {
c() {
const test = () => console.log(this, 1);
test();
}
};
// 同理,test也就是箭头函数是在c函数执行的时候创建,c函数执行的时候this指向是b,所以箭头函数的this是b
// b
b.c()
2、对象属性声明的方式创建箭头函数
const a = {
test: () => console.log(this)
}
// 箭头函数创建的时候,作用域以及父级作用域没有产生this,所以都找不到,最后指向window
a.test() // Window
同理,即使对象镶嵌多层,只要作用域链上没有this产生,最后都指向Window
const c = {
d: {
test: () => console.log(this),
e: {
f: () => console.log(this)
}
}
}
c.d.test() // Window
c.d.e.f() // Window
3、最后来一个深一点的混合创建
const a = {
b() {
const c = {
d: () => console.log(this, 1), // a, 1
e() {
const f = () => console.log(this, 2);
function h() {
const i = f
i()
}
f();
h() // 不会改变箭头函数的指向问题,和f函数执行的时候的this指向相同
}
};
c.d();
c.e(); // c, 2
const g = c.e
g() // Window, 2
}
};
a.b()
// 1、e函数在创建的时候,是以对象属性声明的方式创建,所以自身没有this,就找到父,父是d对象,也没有this,
// 就继续往上寻找,就找到了b函数,b函数调用的时候this指向的是a,所以第一个this就打印a
// 2、f函数是在e函数执行的时候创建,f函数的this就等于e函数的this,e的调用者是c,所以this就等于c
// 3、f函数是在e函数执行的时候创建,f函数的this就等于e函数的this,e函数用g变量保存,就是g函数的调用者,
// g函数是直接执行的,g的调用者是Window,所以f函数的this就等于Window
总结
- this只有在函数调用的时候才会产生,就是函数的调用者;
- 当我们创建箭头函数的时候,如果是在函数执行的时候创建箭头函数,当函数执行的时候会产生一个this,箭头函数的this在创建的时候就指定,且不可更改,这时候就指向函数的this,
- 如果是在对象里面声明对象属性的时候创建的箭头函数,这时候对象里面没有this产生,就按照函数作用域向上寻找this,找到就绑定并使用,找不到最后就指向window