A-A+

javascript之this关键字详解介绍

2016年01月20日 前端设计 暂无评论 阅读 6 views 次

下面一介绍一下关于javascript之this关键字详解介绍,初次接触this,总认为它很强大和神秘。不可预知,似乎有种不为人知的魔力。

因为在接触到它之前,大部分人认为this是那些oop语言的专利。至少我曾经是这么认为的。

随着时间的推移,对javascript的进一步提高。this那神秘的面纱才一步步被揭开。话休绕舌,下面就一起来看看这层神秘的面纱背后的this吧。

首先,我们要知道this是什么。它的含义。通俗的来说, this首先是一个对象,其次要知道的是this不是由它本身出现在何处来决定的。

而是由调用它的对象来决定的,可以简单的理解为。是谁调用了this,那么this便代表谁。比如在全局作用域中调用this。那么此时的this便代表着全局变量。

例:console.log(this === window) 如上文说所的来分析,如是在全局作用域中。this则代表着全局变量。也就是window,那么事实是不是这样呢。运行上面的代码,输出true。证明this的却是window.
如果this是在一个对象中出现,那么正常情况下。this则代表该对象。

例,代码如下:

  1. var obj = {  
  2.    fn:function(){  
  3.       console.log(this === obj);  
  4.   }  
  5. }  

obj.fn();//true弄明白了这两点,this的真相似乎已经浮出水面了。下面我们来看一个复杂点的例子。相信有很多人都会犯错,同时这也是一道经典的面试题,代码如下:

  1. var length = 20;  
  2. function fn(){  
  3.     console.log(this.length);  
  4. }  
  5. var o = {  
  6. length:10,  
  7. e:function (fn){  
  8.     fn();  
  9.    arguments[0]();  
  10. }  
  11. }  

o.e(fn);相信有不少的同鞋会认为让面会输出 20,20; 也有少部分人认为是10,10; 或者20 10,10 20;

但是很遗憾,上面的答案全部错误。先不急着公布正确答案,我们来分析一下,看看在运行中this到底代表什么。

当运行o.e(fn);时,e中的this代表着o。因为是o调用了e。这点相信大家都没有疑问。

当进入e时。执行fn(); 此时的fn也就是参数传递进来的fn,由于函数名只是保存了一个指向函数的引用。所以此时e内部的fn与外面的fn是一模一样的。又因为函数内部的this是由函数的调用者决定的。所以此时fn内的this代表了window。这点相信当家也没有疑问。

当执行arguments[0]()时,由于arguments[0]是函数的第一个参数,等于fn。所以此时的函数也就等于外部的fn,理论上来说this也应该是等于window的。

似乎这么解释是合理的。 那么正确答案就应该是20,20.那么我又为何说上面的答案中没有一个是正确的呢。那是因为我们忽略了一点。那就是,arguments。

由于arguments[0]().相当与arguments.0(); 也就是说,正真调用fn的是arguments。所以函数内部的this应该是arguemnts,所以。this.length 等于参数的个数,也就是1.正确答案是20 1.

相信大家都明白了吧,那么下面我们就来看看是什么样的机制造就了this。

首先,当一个函数被运行时。他都会进入一个新的执行环境,就算是同一个函数两次调用,异或是函数自身递归调用,它们所进入的执行环境都是不同的。

下面就来看看,在JavaScript中各种this的使用方法有什么混乱之处?

1、在HTML元素事件属性中inline方式使用this关键字,代码如下:

  1. <div onclick="  
  2.  // 可以在里面使用this  
  3.  ">division element</div>  
  4.     我们一般比较常用的方法是在此使用:javascirpt: EventHandler(this),这样的形式。不过这里其实可以写任何合法的JavaScript语句,要是高兴在此定义个类也可以(不过将会是个内部类)。这里的原理是脚本引擎生成了一个div实例对象的匿名成员方法,而onclick指向这个方法。  
  5.     2、用DOM方式在事件处理函数中使用this关键字:  
  6.  代码如下   复制代码  
  7.  <div id="elmtDiv">division element</div>  
  8.  <script language="javascript">  
  9.  var div = document.getElementById('elmtDiv');  
  10.  div.attachEvent('onclick', EventHandler);  
  11.  function EventHandler()  
  12.  {  
  13.     // 在此使用this  
  14.  }  
  15.  </script>  

这时的EventHandler()方法中的this关键字,指示的对象是IE的window对象。这是因为EventHandler只是一个普通的函数,对于attachEvent后,脚本引擎对它的调用和div对象本身没有任何的关系。同时你可以再看看EventHandler的caller属性,它是等于null的。如果我们要在这个方法中获得div对象引用,应该使用:this.event.srcElement。

3、用DHTML方式在事件处理函数中使用this关键字,代码如下:

  1. <div id="elmtDiv">division element</div>  
  2. <script language="javascript">  
  3. var div = document.getElementById('elmtDiv');  
  4. div.onclick = function()  
  5. {  
  6.    // 在此使用this  
  7. };  
  8. </script>  

这里的this关键字指示的内容是div元素对象实例,在脚本中使用DHTML方式直接为div.onclick赋值一个EventHandler的方法,等于为div对象实例添加一个成员方法。这种方式和第一种方法的区别是,第一种方法是使用HTML方式,而这里是DHTML方式,后者脚本解析引擎不会再生成匿名方法。

4、类定义中使用this关键字,代码如下:

  1. function JSClass()  
  2. {  
  3.     var myName = 'jsclass';  
  4.     this.m_Name = 'JSClass';  
  5. }  
  6. JSClass.prototype.ToString = function()  
  7. {  
  8.     alert(myName + ', ' + this.m_Name);  
  9. };  
  10. var jc = new JSClass();  
  11. jc.ToString();  

这是JavaScript模拟类定义中对this的使用,这个和其它的OO语言中的情况非常的相识。但是这里要求成员属性和方法必须使用this关键字来引用,运行上面的程序会被告知myName未定义。

5、为脚本引擎内部对象添加原形方法中的this关键字,代码如下:

  1. Function.prototype.GetName = function()  
  2. {  
  3.     var fnName = this.toString();   
  4.     fnName = fnName.substr(0, fnName.indexOf('('));   
  5.     fnName = fnName.replace(/^function/, '');   
  6.     return fnName.replace(/(^s+)|(s+$)/g, '');  
  7. }  
  8. function foo(){}  
  9. alert(foo.GetName());  

这里的this指代的是被添加原形的类的实例,和4中类定义有些相似,没有什么太特别的地方。

6、结合2&4,说一个比较迷惑的this关键字使用,代码如下:

  1. function JSClass()  
  2. {  
  3.     this.m_Text = 'division element';  
  4.     this.m_Element = document.createElement('DIV');  
  5.     this.m_Element.innerHTML = this.m_Text;  
  6.         
  7.     this.m_Element.attachEvent('onclick', this.ToString);  
  8. }  
  9.    
  10. JSClass.prototype.Render = function()  
  11. {  
  12.     document.body.appendChild(this.m_Element);  
  13. }      
  14. JSClass.prototype.ToString = function()  
  15. {  
  16.     alert(this.m_Text);  
  17. };  
  18. var jc = new JSClass();  
  19. jc.Render();   
  20. jc.ToString();  

我就说说结果,页面运行后会显示:"division element",确定后点击文字"division element",将会显示:"undefined"。

7、CSS的expression表达式中使用this关键字,代码如下:

  1. <table width="100" height="100">  
  2.     <tr>  
  3.         <td>  
  4.             <div style="width: expression(this.parentElement.width);   
  5.                   height: expression(this.parentElement.height);">  
  6.                 division element</div>  
  7.         </td>  
  8.     </tr>  
  9. </table>  

这里的this看作和1中的一样就可以了,它也是指代div元素对象实例本身。

8、函数中的内部函数中使用this关键字,代码如下:

  1. function OuterFoo()  
  2. {  
  3.     this.Name = 'Outer Name';  
  4.   
  5.     function InnerFoo()  
  6.     {  
  7.         var Name = 'Inner Name';   
  8.         alert(Name + ', ' + this.Name);  
  9.     }  
  10.     return InnerFoo;  
  11. }  
  12. OuterFoo()();  
标签:

给我留言