JavaScript之this指针深入详解

简介:

javascript中的this含义非常丰富,它可以是全局对象,当前对象或者是任意对象,这都取决于函数的调用方式。函数有以下几种调用方式:作为对象方法调用、作为函数调用、作为构造函数调用、apply或call调用。

对象方法调用

作为对象方法调用的时候,this会被绑定到该对象。


 
 
  1. var point = { 
  2. x : 0, 
  3. y : 0, 
  4. moveTo : function(x, y) { 
  5.      this.x = this.x + x; 
  6.      this.y = this.y + y; 
  7.      } 
  8. }; 

point.moveTo(1, 1)//this 绑定到当前对象,即 point 对象

这里我想强调一点内容,就是this是在函数执行的时候去获取对应的值,而不是函数定义时。即使是对象方法调用,如果该方法的函数属性以函数名的形式传入别的作用域,也会改变this的指向。我举一个例子:


 
 
  1. var a = { 
  2. aa : 0, 
  3. bb : 0, 
  4. fun : function(x,y){ 
  5.   this.aa = this.aa + x; 
  6.   this.bb = this.bb + y; 
  7. }; 
  8. var aa = 1; 
  9. var b = { 
  10. aa:0, 
  11. bb:0, 
  12. fun : function(){return this.aa;} 
  13. a.fun(3,2); 
  14. document.write(a.aa);//3,this指向对象本身 
  15. document.write(b.fun());//0,this指向对象本身 
  16. (function(aa){//注意传入的是函数,而不是函数执行的结果 
  17. var c = aa(); 
  18. document.write(c);//1 , 由于fun在该处执行,导致this不再指向对象本身,而是这里的window 
  19. })(b.fun); 

这样就明白了吧。这是一个容易混淆的地方。

函数调用

函数也可以直接被调用,这个时候this被绑定到了全局对象。


 
 
  1. var x = 1
  2.  function test(){ 
  3.  this.x = 0
  4.  } 
  5.  test(); 
  6.  alert(x); //0 

但这样就会出现一些问题,就是在函数内部定义的函数,其this也会指向全局,而和我们希望的恰恰相反。代码如下:


 
 
  1. var point = { 
  2. x : 0
  3. y : 0
  4. moveTo : function(x, y) { 
  5.      // 内部函数 
  6.      var moveX = function(x) { 
  7.      this.x = x;//this 绑定到了全局 
  8.     }; 
  9.     // 内部函数 
  10.     var moveY = function(y) { 
  11.     this.y = y;//this 绑定到了全局 
  12.     }; 
  13.  
  14.     moveX(x); 
  15.     moveY(y); 
  16.     } 
  17. }; 
  18. point.moveTo(11); 
  19. point.x; //==>0 
  20. point.y; //==>0 
  21. x; //==>1 
  22. y; //==>1 

我们会发现不但我们希望的移动呢效果没有完成,反而会多出两个全局变量。那么如何解决呢?只要要进入函数中的函数时将this保存到一个变量中,再运用该变量即可。代码如下:


 
 
  1. var point = { 
  2. x : 0, 
  3. y : 0, 
  4. moveTo : function(x, y) { 
  5.       var that = this
  6.      // 内部函数 
  7.      var moveX = function(x) { 
  8.      that.x = x; 
  9.      }; 
  10.      // 内部函数 
  11.      var moveY = function(y) { 
  12.      that.y = y; 
  13.      } 
  14.      moveX(x); 
  15.      moveY(y); 
  16.      } 
  17. }; 
  18. point.moveTo(1, 1); 
  19. point.x; //==>1 
  20. point.y; //==>1 

构造函数调用

在javascript中自己创建构造函数时可以利用this来指向新创建的对象上。这样就可以避免函数中的this指向全局了。


  
  
  1. var x = 2; 
  2. function test(){ 
  3. this.x = 1; 
  4. var o = new test(); 
  5. alert(x); //2 

apply或call调用

这两个方法可以切换函数执行的上下文环境,也就是改变this绑定的对象。apply和call比较类似,区别在于传入参数时一个要求是数组,一个要求是分开传入。所以我们以apply为例:


  
  
  1. <pre name="code" class="html">var name = "window"
  2. var someone = { 
  3.     name: "Bob"
  4.     showName: function(){ 
  5.         alert(this.name); 
  6.     } 
  7. }; 
  8.  
  9. var other = { 
  10.     name: "Tom" 
  11. };   
  12.  
  13. someone.showName();  //Bob 
  14. someone.showName.apply();    //window 
  15. someone.showName.apply(other);    //Tom 

可以看到,正常访问对象中方法时,this指向对象。使用了apply后,apply无参数时,this的当前对象是全局,apply有参数时,this的当前对象就是该参数。

箭头函数调用

这里需要补充一点内容,就是在下一代javascript标准ES6中的箭头函数的 this始终指向函数定义时的 this,而非执行时。我们通过一个例子来理解:


  
  
  1. var o = { 
  2.     x : 1, 
  3.     func : function() { console.log(this.x) }, 
  4.     test : function() { 
  5.         setTimeout(function() { 
  6.             this.func(); 
  7.         }, 100); 
  8.     } 
  9. }; 
  10.  
  11. o.test(); // TypeError : this.func is not a function 

上面的代码会出现错误,因为this的指向从o变为了全局。我们需要修改上面的代码如下:


  
  
  1. var o = { 
  2.     x : 1, 
  3.     func : function() { console.log(this.x) }, 
  4.     test : function() { 
  5.         var _this = this
  6.         setTimeout(function() { 
  7.             _this.func(); 
  8.         }, 100); 
  9.     } 
  10. }; 
  11.  
  12. o.test(); 

通过使用外部事先保存的this就行了。这里就可以利用到箭头函数了,我们刚才说过,箭头函数的 this始终指向函数定义时的 this,而非执行时。所以我们将上面的代码修改如下:


  
  
  1. var o = { 
  2.     x : 1, 
  3.     func : function() { console.log(this.x) }, 
  4.     test : function() { 
  5.         setTimeout(() => { this.func() }, 100); 
  6.     } 
  7. }; 
  8.  
  9. o.test(); 

这回this就指向o了,我们还需要注意一点的就是这个this是不会改变指向对象的,我们知道call和apply可以改变this的指向,但是在箭头函数中是无效的。


  
  
  1. var x = 1, 
  2.     o = { 
  3.         x : 10, 
  4.         test : () => this.x 
  5.     }; 
  6.  
  7. o.test(); // 1 
  8. o.test.call(o); // 依然是1 

这样就可以明白各种情况下this绑定对象的区别了。


来源:51CTO

相关文章
|
6月前
|
Java C++
This指针
This指针
43 0
|
5月前
|
数据采集 存储 编译器
this指针如何使C++成员指针可调用
本文介绍了C++中的this指针,它是一个隐藏的指针,用于在成员函数中访问对象实例的成员。文章通过代码示例阐述了this指针的工作原理,以及如何使用指向成员变量和成员函数的指针。此外,还提供了一个多线程爬虫示例,展示this指针如何使成员指针在对象实例上调用,同时利用代理IP和多线程提升爬取效率。
this指针如何使C++成员指针可调用
|
5月前
|
自然语言处理 JavaScript 前端开发
在JavaScript中,this关键字的行为可能会因函数的调用方式而异
【6月更文挑战第15天】JavaScript的`this`根据调用方式变化:非严格模式下直接调用时指向全局对象(浏览器为window),严格模式下为undefined。作为对象方法时,`this`指对象本身。用`new`调用构造函数时,`this`指新实例。`call`,`apply`,`bind`可显式设定`this`值。箭头函数和绑定方法有助于管理复杂场景中的`this`行为。
59 3
|
4月前
|
JavaScript
JS 【详解】双指针排序 -- 数组合并后递增排序
JS 【详解】双指针排序 -- 数组合并后递增排序
28 0
|
4月前
|
JavaScript
js 【详解】函数中的 this 指向
js 【详解】函数中的 this 指向
37 0
|
4月前
|
JavaScript 前端开发
|
6月前
|
JavaScript 前端开发
js中改变this指向、动态指定函数 this 值的方法
js中改变this指向、动态指定函数 this 值的方法
|
5月前
|
JavaScript
js -- 函数总结篇,函数提升、动态参数、剩余参数、箭头函数、this指向......
js -- 函数总结篇,函数提升、动态参数、剩余参数、箭头函数、this指向......
|
5月前
|
编译器 C++
this指针的特性
this指针的特性
23 0
|
5月前
类与对象\this指针
类与对象\this指针
32 0