关于箭头函数里的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这一结论。