this问题
在JavaScript中this是一个特定的关键字,它永远指向的是一个对象,并且this还有一个比较特殊的含义,叫执行上下文,代表着函数的执行者,这简单对的几句话我们可以总结为:
- this指向的是一个对象
- this的指向只跟函数执行时有关,跟函数定义时无关
全局下的this
我们看下面的一个案例
<script> console.log(this); function fn(){ console.log(this) } fn() </script>
所以,全局下的this指向window
对象方法中的this
因为函数在js中既可以当做传递和返回,也可以当做对象和构造函数,所有函数在运行时需要确定其当前的运行环境,this就出生了,所以,this会根据运行环境的改变而改变,同时,函数中的this也只能在运行时才能最终运行环境,以上所说总结一句话概括就是:
函数中的this只有在运行的时候才能确定this的指向,而在定义函数的时候确定不了this的指向
案例1:
<script> function fn(){ console.log(this.a) } var obj={ a:1, fn:fn } var a=2; obj.fn(); //1 fn() //2 </script>
obj.fn()中的fn函数的执行是obj,所以该函数的this指向是obj,所以打印的为1,而fn()执行,它的执行者是window,所以函数中打印的a是window下的a,所以打印的结果为2
案例2:
<script> var A={ name:"小明", fn:function(){ console.log(this.name) } } var B={ name:"小红" } B.f=A.fn; // A.fn() //小明,fn中的执行者是A B.f() //小红,fn中的执行者是B </script>
B.f()执行的时候,它的执行者是B对象,所以打印“小红”,A.fn()执行的时候它的执行者是A,所以打印“小明”。
我们可以得出:函数执行的时候看前面有没有点(.),有点那么函数的执行者就是点前面的对象,没有点那么函数执行者就是window
案例3:
<script> function foo(){ console.log(this.a) } var obj2={ a:1, fun:foo } var obj1={ a:2, fun:obj2 } obj1.fun.fun(); //1 var obj3=obj1.fun; obj3.fun() </script>
永远记住函数的执行者是谁,那么函数中的this就是谁,对于这个案例,连续点运算,采用就近原则,那么函数的执行者是fun,而fun是obj2的这个对象,所以函数中的this执行obj2,所以结果为1 。
常见的this问题大概有一下五种:
- 对象中的方法(小程序中常用)
- 事件绑定
- 构造函数
- 定时器
- 函数对象的call(),apply()方法
如何修改this指向
案例1:
<script> var a=3; var obj1={ a:1 } var obj2={ a:2, fn:function(){ var that=this //用变量取代this setTimeout(function(){ console.log(obj1.a) //1 console.log(that.a) //2 console.log(this.a) //3 },10) } } obj2.fn() </script>
通过提前声明变量解决this指向,往往我们默认采用that或者下划线_this
案例2:
<script> var obj={ a:1 } var obj2={ a:2, fn:function(){ console.log(this.a) } } obj2.fn.call(obj) //1 </script>
通过call函数解决this的指向问题
案例3:
<script> var obj1={ a:1 } var obj2={ a:2, fn:function(){ console.log(this.a) } } obj2.fn.apply(obj1) //1 </script>
通过apply函数解决this的指向问题
案例4:
<script> var obj1={ a:1 } var obj2={ a:2, fn:function(){ console.log(this.a) }.bind(obj1) } obj2.fn() //1 </script>
通过在定义函数的时候在函数的结尾处使用bind()函数修改this指向
//小明,fn中的执行者是A B.f() //小红,fn中的执行者是B