JS如何正确判断 this?箭头函数的 this 是什么?

634 阅读2分钟

话不多说,直接先来看几个函数调用的场景

function foo() {
  console.log(this.a);
};

let a = 1;
foo();

const obj = {
  a: 2,
  foo: foo
};
obj.foo();

const c = new foo();

接下来一个个分析上面的场景

  • 对于直接调用foo来说,不管foo函数被放在了什么地方,this 一定是指向 window

  • 对于obj.foo()来说,只需记住,谁调用了函数,谁就是this,所以在这个场景下foo函数中的this就是obj对象

  • 对于new来说,this被永远绑定在了c上面,不会被任何方式改变this

再来看看箭头函数中的this

function a() {
  return () => {
    return ()=> {
      console.log(this);
    };
  };
};

console.log(a()()());

首先箭头函数其实是没有this的,箭头函数中的this只取决于包裹箭头函数的第一个普通函数的this。在上面这个例子中,因为包裹箭头函数的第一个普通函数就是a,所以此时的this是window。另外对箭头函数使用bind这类函数是无效。

最后情况也就是bind这些改变上下文API了,对于这些函数来说,this取决于第一个参数,如果第一个参数为空,那么就是window。

如果对一个函数进行多次bind的情况下

let a = {};
let fn = function() { console.log(this) };
fn.bind().bind(a)()  // => 打印出什么?

其实可以把上诉代码转换成另一种形式

let fn2 = function fn1() {
  return function() {
    return fn.apply()
  }.apply(a)
};

fn2();

可以从上诉代码中发现,不管我们给函数bind几次,fn中的this永远由第一次bind决定,所以结果永远是window。

let a = { name: 'xyz' };
function foo() {
  console.log(this.name);
};

foo.bind(a)(); // => 'xyz'

当多个规则同时出现的情况,这时候不同的规则之间会根据优先级最高的来决定this最终指向哪里。

首先,new方式优先级别最高,接下来是bind这些函数,然后是obj.foo()这种调用方式,最后是foo这种调用方式,同时,箭头函数的this一旦被绑定,就不会再被任何方式改变。

最后是关于this指向的流程图,帮助梳理思路(只针对于单个规则)

---END---