![690ef68c07c849a96bab886f27c2f693.png](https://img-blog.csdnimg.cn/img_convert/690ef68c07c849a96bab886f27c2f693.png)
在JS的学习中,有一个很让人困扰的问题,就是关键字this的指向问题。我在学习到一块的时候,也存在了很大的问题,并且还有很多的误区。为了更好的学习JS,那么我就来整理一下JS关键字的指向问题。
首先JS中的this的指向不是指定义它的位置,而是谁定义它,它指向谁。这句话是this指向的根本,一定要牢记。接下来,我来整理一下各种情况下的this指向。
1、 函数自调用
关键字声明的函数,在调用的时候,this被绑定为全局环境,在浏览器环境下,this就指向window对象。
![cf14ecfbda6c20b55634dc438df79ace.png](https://img-blog.csdnimg.cn/img_convert/cf14ecfbda6c20b55634dc438df79ace.png)
2、 对象中作为方法被调用
当函数被保存到对象中,作为对象的一个方法被调用时,this就被绑定到这个对象上,所以this的指向就是该对象。
![db457b3fa03267b269dbe4d9aebd1cdc.png](https://img-blog.csdnimg.cn/img_convert/db457b3fa03267b269dbe4d9aebd1cdc.png)
这里的this指向的就是obj对象,因为这个fn方法被obj对象调用了,根据谁调用,this指向谁的原则,fn方法里面的this指向obj对象。
![ca799e03251679727df9e0270d9e72de.png](https://img-blog.csdnimg.cn/img_convert/ca799e03251679727df9e0270d9e72de.png)
这里Obj对象的obj2属性的值也是一个对象,而obj2这个对象的里面有一个fun方法,这里通过obj.obj2获取的obj2这个对象,再通过这个对象调用fun方法,所以这里的this指向调用fun这个方法的obj2这个对象,由于obj2对象里面没有names属性,所以this.name是undefined。这里还有一个容易让人误会的误区,就是很多人会误以为可以有一个原型链的关系在,会往上一层查找names属性,其实不然,obj2只是obj的一个属性,并没有原型链的关系,所以在调用fun方法的时候,由于obj2中并不存在 names属性,所以this.names的值是undefined。
![bff4d94e005e1aabb1202ad5acdd1025.png](https://img-blog.csdnimg.cn/img_convert/bff4d94e005e1aabb1202ad5acdd1025.png)
那么同样是调用fun方法,为什么这里的this.name的值会是“我是全局变量”呢?其实原因很简单,因为obj.obj2.fun不是调用,只是赋值,这个相当于为全局变量t赋值了一个函数。实际上的效果就是:
![51d79510af61aa55640b391f38206a36.png](https://img-blog.csdnimg.cn/img_convert/51d79510af61aa55640b391f38206a36.png)
而t是全局变量,当t被调用时,指向的当然是全局对象window对象,而全局对象里有一个定义的变量names,所以this.names是“我是全局变量”。
3、 构造函数的调用
如果在一个函数的的调用前面加上new关键字,就会创建一个新的对象,我们称这个对象为函数的实例对象,而该函数就是这个实例对象的构造函数。
![ebea01d5badbad7c0469852488ae4eda.png](https://img-blog.csdnimg.cn/img_convert/ebea01d5badbad7c0469852488ae4eda.png)
上面这个就是一个最简单的构造函数实例化,我们可以看到this的指向是一个对象,而非一个函数,所以得出结论,实例化一个构造函数后,this的指向指向的就是这个实例化得出的对象,也就是实例对象。
![af36a08a7baa4bcea5f18f548ae111b4.png](https://img-blog.csdnimg.cn/img_convert/af36a08a7baa4bcea5f18f548ae111b4.png)
实例对象a和实例对象b都来自于fn这个构造函数实例化得出的,而实例对象是独立的两个个体,所以虽然它们new自同一个构造函数,但是它们的this指向分别是它们自己,实例对象b的this指向就是实例对象b自己,而实例对象a指的也是实例对象a自己,进一步说明了,构造函数实例化后,构造函数里面的this指向的是实例化这个构造函数的实例对象。
4、 事件的调用
还是那个句话,谁调用this就指向谁,这句话在事件里面也是一样的。
![15ff1d4b51426877880dfb0de67c3fe4.png](https://img-blog.csdnimg.cn/img_convert/15ff1d4b51426877880dfb0de67c3fe4.png)
点击input,把input的值由按钮变成修改,这里this就是指向调用点击事件的input这个节点对象。
上面罗列了这么多this的指向,那么this的指向可以改变吗?其实是可以改变的,可以通过以下四种方法来对this的指向进行改变。
1、 call方法:固定函数this的指向对象
传入哪个对象,this就指向哪个对象。
语法 :函数名.call(指向对象,实参1,实参2...):实参在对象后面用','隔开
![ffdb54f9372c9234e465586d033712b1.png](https://img-blog.csdnimg.cn/img_convert/ffdb54f9372c9234e465586d033712b1.png)
通过call方法把this的指向固定给了li这个对象
2、 apply方法:固定函数this的指向对象
传入哪个对象,this就指向哪个对象
语法:函数名.apply(指向对象,[实参1,实参2...]):实参在对象后面用数组包装起来,一起传入
和call方法的功能一样,用法也差不多,唯一的区别就是传参的方式不同,这个需要把参数用一个数组包裹起来。
![7e0479432caa09183a7551e0a30dbe2f.png](https://img-blog.csdnimg.cn/img_convert/7e0479432caa09183a7551e0a30dbe2f.png)
3、 bind方法:创建一个新的函数,且将新函数中的this绑定到具体的某个对象上
语法:函数名.bind(对象)
![9ccc7e5b920697a179010fc585d6a0f4.png](https://img-blog.csdnimg.cn/img_convert/9ccc7e5b920697a179010fc585d6a0f4.png)
4、 ES6里面的箭头函数
箭头函数没有自己的this,函数体内部写的this固定指向的是它的上一层的环境,箭头函数内部的this是定义时所在的对象,而不是使用时所在的对象并且不会改变。
![3ed05db309491e07a672aa97588db925.png](https://img-blog.csdnimg.cn/img_convert/3ed05db309491e07a672aa97588db925.png)
以上就是JS里面关于this的指向的整理,总结起来就是一句话,谁调用它,this就指向谁,箭头函数除外。