搜索
首页web前端js教程js里的this关键字的理解

js里的this关键字的理解

Jul 07, 2017 am 10:35 AM
javascriptthis关键字

this关键字相信大家都非常熟悉,js中提供的this关键在要比oo语言中混乱,下面通过本文给大家介绍js里this关键字的理解,需要的朋友可以参考下

this关键字在c++,java中都提供了这个关键字,在刚开始学习时觉得有难度,但是只要理解了,用起来就方便多了,下面通过本篇文章给大家详解js里this关键字的理解。

关于this,是很多前端面试必考的题目,有时候在网上看到这些题目,自己试了一下,额,还真的错了!在实际开发中,也会遇到 this 的问题(虽然一些类库会帮我们处理),例如在使用一些框架的时候,例如:knockout,有时候不明白为什么不直接使用this,而要把 this 作为参数传入。

   接下来你谈谈我对它的理解,也作为一个笔记,方便以后参阅。有不对的地方,欢迎指出批评。

   1. 不像C#,this一定是指向当前对象。

js的this指向是不确定的,也就是说是可以动态改变的。call/apply 就是用于改变this指向的函数,这样设计可以让代码更加灵活,复用性更高。

   2. this 一般情况下,都是指向函数的拥有者。

这一点很重要!这一点很重要!这一点很重要!

   这也是一道常见的面试题,如下代码:

<script type="text/javascript">
  var number = 1;
  var obj = {
     number: 2,
    showNumber: function(){
      this.number = 3;
      (function(){          
        console.log(this.number);
      })();
      console.log(this.number);
    }
  };
  obj.showNumber();
</script>

  由于showNumber方法的拥有者是obj,所以this.number=3; this 指向的就是 obj 的属性 number。

  同理,第二个 console.log 打印的也是属性 number。

   为什么第二点说一般情况下this都是指向函数的拥有者,因为有特殊情况。函数自执行就是特殊情况,在函数自执行里,this 指向的是:window。所以第一个 console.log 打印的是 window 的属性 number。

   所以要加一点:

   3. 在函数自执行里,this 指向的是 window 对象。

   扩展,关于this,还有一个地方比较让人模糊的是在 dom 事件里,通常有如下3种情况:

   如下:

   1. 使用标签属性注册事件,此时this 指向的是 window 对象。

<input id="test" type="button" value="按钮" onClick="test()"/>
  function test(){alert(this)}

   2. 对于1,要让 this 指向 input,可以将 this 作为参数传递。

   3. 使用 addEventListener 等注册。此时this 也是指向 input。

document.getElementById("test").addEventListener("click",test);

   在面向对象编程语言中,对于this关键字我们是非常熟悉的。比如C++、C#和Java等都提供了这个关键字,虽然在开始学习的时候觉得比较难,但只要理解了,用起来是非常方便和意义确定的。JavaScript也提供了这个this关键字,不过用起来就比经典OO语言中要"混乱"的多了。

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

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

// 可以在里面使用this  
">pision element 
 // 可以在里面使用this
 ">pision element

我们一般比较常用的方法是在此使用:javascirpt: EventHandler(this),这样的形式。不过这里其实可以写任何合法的JavaScript语句,要是高兴在此定义个类也可以(不过将会是个内部类)。这里的原理是脚本引擎生成了一个p实例对象的匿名成员方法,而onclick指向这个方法。

   2、用DOM方式在事件处理函数中使用this关键字:

pision element

 var p = document.getElementById(&#39;elmtp&#39;);  
 p.attachEvent(&#39;onclick&#39;, EventHandler);  
 
 function EventHandler()  
 {  
 // 在此使用this  
 }  
  
// --> 
 
pision element

 var p = document.getElementById(&#39;elmtp&#39;);
 p.attachEvent(&#39;onclick&#39;, EventHandler);

 function EventHandler()
 {
 // 在此使用this
 }
 
// -->

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

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

pision element
  
lt;mce:script language="javascript">
var p = document.getElementById(&#39;elmtp&#39;);  
p.onclick = function()  
{  
 // 在此使用this  
};  
 
/ --> 
 
pision element

 var p = document.getElementById(&#39;elmtp&#39;);
 p.onclick = function()
 {
 // 在此使用this
 };
 
// -->

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

  4、类定义中使用this关键字:

function JSClass()  
{  
var myName = &#39;jsclass&#39;;  
this.m_Name = &#39;JSClass&#39;;  
}  
 
JSClass.prototype.ToString = function()  
{  
alert(myName + &#39;, &#39; + this.m_Name);  
};  
 
var jc = new JSClass();  
jc.ToString(); 
 function JSClass()
 {
 var myName = &#39;jsclass&#39;;
 this.m_Name = &#39;JSClass&#39;;
 }

 JSClass.prototype.ToString = function()
 {
 alert(myName + &#39;, &#39; + this.m_Name);
 };

 var jc = new JSClass();
 jc.ToString();

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

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

function.prototype.GetName = function()  
{  
var fnName = this.toString();  
fnName = fnName.substr(0, fnName.indexOf(&#39;(&#39;));  
fnName = fnName.replace(/^function/, &#39;&#39;);  
return fnName.replace(/(^\s+)|(\s+$)/g, &#39;&#39;);  
}  
function foo(){}  
alert(foo.GetName());  
 function.prototype.GetName = function()
 {
 var fnName = this.toString(); 
 fnName = fnName.substr(0, fnName.indexOf(&#39;(&#39;)); 
 fnName = fnName.replace(/^function/, &#39;&#39;); 
 return fnName.replace(/(^\s+)|(\s+$)/g, &#39;&#39;);
 }
 function foo(){}
 alert(foo.GetName());

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

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

view plaincopy to clipboardprint?
function JSClass()  
{  
this.m_Text = &#39;pision element&#39;;  
this.m_Element = document.createElement(&#39;p&#39;);  
this.m_Element.innerHTML = this.m_Text;  
  
this.m_Element.attachEvent(&#39;onclick&#39;, this.ToString);  
}  
  
JSClass.prototype.Render = function()  
{  
document.body.appendChild(this.m_Element);  
}   
 
JSClass.prototype.ToString = function()  
{  
alert(this.m_Text);  
};  
 
var jc = new JSClass();  
jc.Render();  
jc.ToString(); 
 function JSClass()
 {
 this.m_Text = &#39;pision element&#39;;
 this.m_Element = document.createElement(&#39;p&#39;);
 this.m_Element.innerHTML = this.m_Text;
  
 this.m_Element.attachEvent(&#39;onclick&#39;, this.ToString);
 }
  
 JSClass.prototype.Render = function()
 {
 document.body.appendChild(this.m_Element);
 } 

 JSClass.prototype.ToString = function()
 {
 alert(this.m_Text);
 };

 var jc = new JSClass();
 jc.Render(); 
 jc.ToString();

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

  7、CSS的expression表达式中使用this关键字:

height: expression(this.parentElement.height);">  
 pision element  
  
 height: expression(this.parentElement.height);">
 pision element

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

  8、函数中的内部函数中使用this关键字:

view plaincopy to clipboardprint?
function OuterFoo()  
{  
this.Name = &#39;Outer Name&#39;;  
 
function InnerFoo()  
{  
var Name = &#39;Inner Name&#39;;  
alert(Name + &#39;, &#39; + this.Name);  
}  
return InnerFoo;  
}  
OuterFoo()(); 
 function OuterFoo()
 {
 this.Name = &#39;Outer Name&#39;;
 
 function InnerFoo()
 {
 var Name = &#39;Inner Name&#39;; 
 alert(Name + &#39;, &#39; + this.Name);
 }
 return InnerFoo;
 }
 OuterFoo()();

  运行结果显示是:"Inner Name, Outer Name"。按我们在2中的讲解,这里的结果如果是"Inner Name, undefined"似乎更合理些吧?但是正确的结果确实是前者,这是由于JavaScript变量作用域的问题决定的,详细了解推荐参看"原来JScript中的关键字'var'还是有文章的"一文及回复。

    归纳起来,JavaScript中的this用法有以下3种(详细用法参原文):

    1.在HTML元素事件属性 或 CSS的expression表达式 中inline方式使用this关键字——对应原文的1、7

    2.在事件处理函数中使用this关键字——对应原文的2、3

      其中可分为两种方式

      (1)DOM方式——此种方式的结果是this指向窗口(window)对象

      (2)DHTML方式——此种方式的结果是this指向p元素对象实例

    3.在类定义中使用this关键字并在其 内部函数 或 成员函数(主要是prototype产生)中使用——对应原文的4、5、8

      需要说明的是,在函数也是个对象,因此需要区分 变量定义 和 成员变量定义,如下:

view plaincopy to clipboardprint?

var variableName;    //变量定义  
//作用域:函数定义范围内  
//使用方法:直接使用variableName  
this.varName;      //成员变量定义  
//作用域:函数对象定义范围内及其成员函数中  
//使用方法:this.varName 
var variableName;    //变量定义
//作用域:函数定义范围内
//使用方法:直接使用variableName
this.varName;      //成员变量定义
//作用域:函数对象定义范围内及其成员函数中
//使用方法:this.varName

 以上归纳出的三类this的使用方法中,第一种比较容易理解,这里对原文中第6点提到的程序进行了测试和改进如下,以说明上述后两种使用方法:

view plaincopy to clipboardprint?

    function JSClass()  
    {  
      var varText = "func variable!";                 //函数中的普通变量  
      this.m_Text = &#39;func member!&#39;;                    //函数类的成员变量  
      this.m_Element = document.createElement(&#39;p&#39;);   //成员变量,创建一个p对象  
      this.m_Element.innerHTML = varText;             //使用函数的普通变量  
      this.m_Element.attachEvent(&#39;onclick&#39;, this.ToString);  //给这个对象的事件连上处理函数  
      this.newElement = document.createElement(&#39;p&#39;);  
      this.newElement.innerHTML = "new element";   
      this.newElement.m_Text = "new element text!";      //给创建的对象建个成员  
      this.newElement.onclick = function()  
      {  
        alert(this.m_Text);                       //指向p对象的成员  
      };  
    }  
   
    JSClass.prototype.Render = function()  
    {  
      document.body.appendChild(this.m_Element);       //把p对象挂在窗口上  
      document.body.appendChild(this.newElement);  
    }    
 
    JSClass.prototype.ToString = function()  
    {  
      alert(this.m_Text);                         //指向窗口(window)对象  
    };  
 
    function initialize(){  
      var jc = new JSClass();  
      jc.Render();  
      jc.ToString();                             //里面的this指向JSClass类的实例,里面有m_Text成员  
    }  
    
// -->  

    initialize();  
    
// -->  
  
 function JSClass()
  {
   var varText = "func variable!";     //函数中的普通变量
    this.m_Text = &#39;func member!&#39;;     //函数类的成员变量
    this.m_Element = document.createElement(&#39;p&#39;); //成员变量,创建一个p对象
    this.m_Element.innerHTML = varText;    //使用函数的普通变量
    this.m_Element.attachEvent(&#39;onclick&#39;, this.ToString); //给这个对象的事件连上处理函数
    this.newElement = document.createElement(&#39;p&#39;);
    this.newElement.innerHTML = "new element"; 
    this.newElement.m_Text = "new element text!";  //给创建的对象建个成员
    this.newElement.onclick = function()
   {
     alert(this.m_Text);      //指向p对象的成员
   };
  }
  
  JSClass.prototype.Render = function()
  {
    document.body.appendChild(this.m_Element);  //把p对象挂在窗口上
    document.body.appendChild(this.newElement);
  }   

  JSClass.prototype.ToString = function()
  {
    alert(this.m_Text);       //指向窗口(window)对象
  };

 function initialize(){
   var jc = new JSClass();
   jc.Render(); 
   jc.ToString();        //里面的this指向JSClass类的实例,里面有m_Text成员
  }
  
// -->

   initialize();
  
// -->

上面的代码执行结果是:

页面加载时,弹出对话框,输出func member!

页面上显示

 func variable!
 new element

单击func variable时,弹出对话框,显示undefined

  ——因为这时toString函数里的this指针指向window

单击new element时,弹出对话框显示new element text!

  ——因为这时toString函数里的this指针指向p元素,而该元素已经定义了m_Text成员(this.newElement.m_Text = "new element text!")

以上是js里的this关键字的理解的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
幕后:什么语言能力JavaScript?幕后:什么语言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在浏览器和Node.js环境中运行,依赖JavaScript引擎解析和执行代码。1)解析阶段生成抽象语法树(AST);2)编译阶段将AST转换为字节码或机器码;3)执行阶段执行编译后的代码。

Python和JavaScript的未来:趋势和预测Python和JavaScript的未来:趋势和预测Apr 27, 2025 am 12:21 AM

Python和JavaScript的未来趋势包括:1.Python将巩固在科学计算和AI领域的地位,2.JavaScript将推动Web技术发展,3.跨平台开发将成为热门,4.性能优化将是重点。两者都将继续在各自领域扩展应用场景,并在性能上有更多突破。

Python vs. JavaScript:开发环境和工具Python vs. JavaScript:开发环境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

JavaScript是用C编写的吗?检查证据JavaScript是用C编写的吗?检查证据Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C语言编写的。1)C语言提供了高效性能和底层控制,适合JavaScript引擎的开发。2)以V8引擎为例,其核心用C 编写,结合了C的效率和面向对象特性。3)JavaScript引擎的工作原理包括解析、编译和执行,C语言在这些过程中发挥关键作用。

JavaScript的角色:使网络交互和动态JavaScript的角色:使网络交互和动态Apr 24, 2025 am 12:12 AM

JavaScript是现代网站的核心,因为它增强了网页的交互性和动态性。1)它允许在不刷新页面的情况下改变内容,2)通过DOMAPI操作网页,3)支持复杂的交互效果如动画和拖放,4)优化性能和最佳实践提高用户体验。

C和JavaScript:连接解释C和JavaScript:连接解释Apr 23, 2025 am 12:07 AM

C 和JavaScript通过WebAssembly实现互操作性。1)C 代码编译成WebAssembly模块,引入到JavaScript环境中,增强计算能力。2)在游戏开发中,C 处理物理引擎和图形渲染,JavaScript负责游戏逻辑和用户界面。

从网站到应用程序:JavaScript的不同应用从网站到应用程序:JavaScript的不同应用Apr 22, 2025 am 12:02 AM

JavaScript在网站、移动应用、桌面应用和服务器端编程中均有广泛应用。1)在网站开发中,JavaScript与HTML、CSS一起操作DOM,实现动态效果,并支持如jQuery、React等框架。2)通过ReactNative和Ionic,JavaScript用于开发跨平台移动应用。3)Electron框架使JavaScript能构建桌面应用。4)Node.js让JavaScript在服务器端运行,支持高并发请求。

Python vs. JavaScript:比较用例和应用程序Python vs. JavaScript:比较用例和应用程序Apr 21, 2025 am 12:01 AM

Python更适合数据科学和自动化,JavaScript更适合前端和全栈开发。1.Python在数据科学和机器学习中表现出色,使用NumPy、Pandas等库进行数据处理和建模。2.Python在自动化和脚本编写方面简洁高效。3.JavaScript在前端开发中不可或缺,用于构建动态网页和单页面应用。4.JavaScript通过Node.js在后端开发中发挥作用,支持全栈开发。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

VSCode Windows 64位 下载

VSCode Windows 64位 下载

微软推出的免费、功能强大的一款IDE编辑器