关于箭头函数里的this这个问题一直很模糊,之前看了很多教程虽然知道了其行为,但是具体实现规则一直不太清晰。今天为了彻底搞懂这个问题,查了很多资料,感觉查到的很多例子不是很能清晰的描述这种行为。所以今天特地自己写一遍文章来说明一下。
普通函数里的this
先来说一下普通函数里的this。
1 | var a = 1 |
在普通函数里,this的值在定义时是不明确的,要等到调用时才能确定,谁调用就指向谁。上面代码里的test()是在全局作用域调用的,所以自然就指向window,控制台会打印1。
再来看一个例子:
1 | var a = 1 |
上面的代码我们把test函数定义在里对象obj里,调用的时候是用obj来调用的,所以test函数里的this自然就指向obj,最后函数会打印2。
再来看一个:
1 | var a = 1 |
上面的代码我们把obj.test函数里的代码赋值给了一个全局变量w,然后用全局变量w调用了test函数,所以这里的this指向的也是window。
还有一种情况:
1 | var a = 1 |
这里来看obj.test方法,这个方法里我们创建了一个fn函数,最后将fn函数的结果作为obj.test的结果返回,这里的fn是用return方法返回的,并没有被其它对象直接调用,普通函数里this也并不会被继承,所以这里的this指向全局的window。
setTimeout方法和setInterval方法中的this均指向window,如下:
1 | var a = 1 |
上面的几种情况就是普通函数里this的指向。
使用call()、apply()、bind()等方法可以手动改变普通函数里this的指向,在本文里就不详细叙述了。
箭头函数里的this
先说结论:
- 箭头函数不会创建自己的
this,它只会从自己的作用域链的上一层继承this(结论出自MDN - 箭头函数) - 使用call()、apply()、bind()等方法并不会直接修改箭头函数内的this
- 箭头函数的this是在创建时就已经确定了
1 | var a = 1 |
这里的this是在箭头函数里的,所以会从自己的作用域链的上一层,也就是obj对象来继承this。最后一行obj是在全局中调用的,所以obj的this指向window,其结果打印的是1。
1 | function a() { |
上面的这个例子,c是箭头函数,所以c里的this继承自己的作用域链的上一层b,b是直接return返回的结果,this指向window。
我们再把上面的例子修改一下:
1 | var obj = { |
上面的例子我们手动用call()方法把b的this指向更改为了obj,通过打印出来的结果再一次印证了箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this这一结论。