当前位置: 首页 > 科技观察

JavaScript中this指针深入讲解

时间:2023-03-13 23:47:32 科技观察

javascript这个有很丰富的含义,可以是全局对象,也可以是当前对象,也可以是任何对象,这都取决于函数的调用方式。调用函数有几种方式:作为对象方法调用、作为函数调用、作为构造函数调用、apply或call调用。当对象方法调用作为对象方法调用时,this将绑定到对象上。varpoint={x:0,y:0,moveTo:function(x,y){this.x=this.x+x;this.y=this.y+y;}};point.moveTo(1,1)//this绑定到当前对象,即点对象。这里要强调一下,这里是在函数执行的时候获取对应的值,而不是在定义函数的时候。即使是对象方法调用,如果将方法的函数属性以函数名的形式传递给另一个作用域,this的指向也会发生变化。让我举个例子:vara={aa:0,bb:0,fun:function(x,y){this.aa=this.aa+x;this.bb=this.bb+y;}};varaa=1;varb={aa:0,bb:0,fun:function(){returnthis.aa;}}a.fun(3,2);document.write(a.aa);//3,this指向对象Document.write(b.fun());//0,this指向对象本身(function(aa){//注意传入的是函数,不是函数执行的结果varc=aa();document.write(c);//1、因为fun是在那里执行的,所以this不再指向对象本身,而是这里的window})(b.fun);所以你可以理解。这是一个令人困惑的领域。函数调用函数也可以直接调用,此时this绑定在全局对象上。varx=1; functiontest(){ this.x=0; } test(); alert(x);//0但是会有一些问题,它是一个定义在函数内部的函数,它的this也会指向全局,这和我们想要的恰恰相反。代码如下:varpoint={x:0,y:0,moveTo:function(x,y){//内部函数varmoveX=function(x){this.x=x;//this绑定到global};//内部函数varmoveY=function(y){this.y=y;//this绑定到global};moveX(x);moveY(y);}};point.moveTo(1,1);point.x;//==>0point.y;//==>0x;//==>1y;//==>1我们会发现不仅不是我们想要的运动效果完成了,但是会多出两个全局变量。那么如何解决呢?函数中要进入函数的时候把这个保存在一个变量中,然后使用这个变量就可以了。代码如下:varpoint={x:0,y:0,moveTo:function(x,y){varthat=this;//内部函数varmoveX=function(x){that.x=x;};//internalfunctionvarmoveY=function(y){that.y=y;}moveX(x);moveY(y);}};point.moveTo(1,1);point.x;//==>1point。y;//==>1构造函数调用在javascript中创建构造函数时,可以使用this指向新创建的对象。这样可以防止函数中的this指向全局。varx=2;  functiontest(){    this.x=1;  }  varo=newtest();  alert(x);//2apply或者调用调用这两个method可以切换函数执行的上下文,即改变this绑定的对象。apply和call类似,不同的是在传入参数的时候,一个要求是数组,一个要求是单独传入。那么让我们以应用为例:varname="window";varsomeone={name:"Bob",showName:function(){alert(this.name);}};varother={name:"Tom"};someone.showName();//Bobsomeone.showName.apply();//windowsomeone.showName.apply(other);//Tom在访问对象中的方法时可以看到通常,this指向对象。使用apply后,当apply没有参数时,this的当前对象是全局的,当apply有参数时,this的当前对象是参数。箭头函数调用这里需要加点东西,就是下一代javascript标准ES6中箭头函数的this总是在函数定义的时候指向this,而不是在函数执行的时候指向this。我们通过一个例子来理解:varo={x:1,func:function(){console.log(this.x)},test:function(){setTimeout(function(){this.func();},100);}};o.test();//TypeError:this.funcisnotfunction上面的代码会报错,因为this的point从o变成了global。我们需要将上面的代码修改为:varo={x:1,func:function(){console.log(this.x)},test:function(){var_this=this;setTimeout(function(){_this.func();},100);}};o.test();只需使用外部保存的即可。这里可以使用箭头函数。刚才我们说了,箭头函数的this总是指向函数定义的this,而不是在执行的时候。所以我们修改上面的代码如下:varo={x:1,func:function(){console.log(this.x)},test:function(){setTimeout(()=>{this.func()},100);}};o.test();这次this指向o,还要注意this不会改变指向的对象,我们知道call和apply可以改变this的指向,但是在箭头函数中是无效的。varx=1,o={x:10,test:()=>this.x};o.test();//1o.test.call(o);//还是1这样你就明白了各种情况下此绑定对象之间的区别。