几个函数看懂箭头函数this的指向问题

424 阅读3分钟

众所周知,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() 

image.png

// 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
总结
  1. this只有在函数调用的时候才会产生,就是函数的调用者;
  2. 当我们创建箭头函数的时候,如果是在函数执行的时候创建箭头函数,当函数执行的时候会产生一个this,箭头函数的this在创建的时候就指定,且不可更改,这时候就指向函数的this,
  3. 如果是在对象里面声明对象属性的时候创建的箭头函数,这时候对象里面没有this产生,就按照函数作用域向上寻找this,找到就绑定并使用,找不到最后就指向window