>  기사  >  웹 프론트엔드  >  js에서 this 키워드 이해하기

js에서 this 키워드 이해하기

怪我咯
怪我咯원래의
2017-07-07 10:35:091454검색

js에서 제공하는 this 키는 oo 언어에서 제공하는 키워드보다 더 헷갈리는 것 같아요. 이 글은 js에서 이 키워드를 이해하는 방법을 소개할 것입니다.

이 키워드는 C++과 Java에서 모두 제공됩니다. 처음 배울 때는 어렵지만, 일단 이해하고 나면 js에서 이 키워드를 이해하는 방법에 대한 자세한 설명이 나와 있습니다. 이 글을 통해.

이에 대해서는 많은 프론트엔드 면접에서 필수 질문인데요, 가끔 인터넷에서 이런 질문들을 보고 직접 해보기도 합니다. 실제 개발에서도 이 문제에 직면하게 됩니다(일부 클래스 라이브러리가 이 문제를 해결하는 데 도움이 되지만). 예를 들어 녹아웃과 같은 일부 프레임워크를 사용할 때 때때로 우리는 이것을 직접 사용하지 않는 이유를 이해하지 못합니다. , 그러나 매개변수가 전달되므로 이를 사용하십시오.

다음으로 제가 이해한 내용에 대해 말씀해 주시고, 향후 참고를 위한 참고 자료로도 활용하겠습니다. 잘못된 점이 있으면 지적하고 비판해 주시기 바랍니다.

1. C#과 달리 현재 개체를 가리켜야 합니다.

js의 이 지점은 불확실합니다. 이는 동적으로 변경될 수 있음을 의미합니다. 호출/적용은 이것이 가리키는 지점을 변경하는 데 사용되는 함수입니다. 이 디자인은 코드를 더 유연하고 재사용 가능하게 만들 수 있습니다.

2. 이는 일반적으로 함수의 소유자를 나타냅니다.

이것은 매우 중요합니다! 이것은 매우 중요합니다! 이것은 매우 중요합니다!

이는 다음 코드에서 볼 수 있듯이 일반적인 인터뷰 질문이기도 합니다.

<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은 obj의 속성 번호를 가리킵니다.

마찬가지로 두 번째 console.log도 속성 번호를 인쇄합니다.

두 번째 요점이 일반적으로 이것이 함수의 소유자를 가리킨다고 말하는 이유는 특별한 상황이 있기 때문입니다. 함수 자체 실행은 특별한 경우입니다. 함수 자체 실행에서는 다음을 가리킵니다. 따라서 첫 번째 console.log는 창의 속성 번호를 인쇄합니다.

그래서 우리는 뭔가를 추가해야 합니다:

3. 함수 자체 실행에서 이것은 창 개체를 가리킵니다.

확장에 대해 또 다른 혼란스러운 점은 DOM 이벤트에는 일반적으로 세 가지 상황이 있다는 것입니다.

다음과 같습니다:

1. label 속성을 사용하여 이벤트를 등록합니다. 이때 이것은 다음을 가리킵니다. 창 개체.

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

2. 1의 경우 이 지점을 입력으로 만들려면 이를 매개변수로 전달할 수 있습니다.

3. addEventListener를 사용하여 등록합니다. 이때 이 역시 입력을 가리킨다.

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

객체 지향 프로그래밍 언어에서 우리는 this 키워드에 매우 익숙합니다. 예를 들어 C++, C#, Java 모두 이 키워드를 제공합니다. 학습 초기에는 어렵지만 일단 이해하고 나면 사용하기가 매우 편리하고 의미가 있습니다. JavaScript도 이 키워드를 제공하지만 기존 OO 언어보다 사용하기가 훨씬 더 "혼란"합니다.

JavaScript에서 이것을 사용하는 다양한 방법에 대해 혼란스러운 점을 살펴보겠습니다.

1. HTML 요소의 이벤트 속성에 이 키워드 인라인을 사용합니다.

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

가장 일반적으로 사용되는 방법은 여기에서 사용하는 것입니다: javascirpt: EventHandler(this), 이 형식. 그러나 실제로 여기에서 합법적인 JavaScript 문을 작성할 수 있습니다. 여기에서 클래스를 정의할 수 있습니다(그러나 이는 내부 클래스가 됩니다). 여기서 원칙은 스크립트 엔진이 p 인스턴스 개체의 익명 member 메서드를 생성하고 onclick이 이 메서드를 가리킨다는 것입니다.

2. 이벤트 처리 함수에서 this 키워드를 사용하려면 DOM 메서드를 사용하세요.

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 창 개체임을 나타냅니다. 이는 EventHandler가 단지 일반 함수이기 때문입니다. attachmentEvent 이후 스크립트 엔진의 호출은 p 개체 자체와 관련이 없습니다. 동시에 null과 동일한 EventHandler의 호출자 속성을 볼 수 있습니다. 이 메소드에서 p 객체 참조를 얻으려면 this.event.srcElement를 사용해야 합니다.

3. 이벤트 처리 기능에서 이 키워드를 사용하려면 DHTML을 사용하세요.

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에 직접 할당합니다. .method는 p 개체 인스턴스에 멤버 메서드를 추가하는 것과 같습니다. 이 방법과 첫 번째 방법의 차이점은 첫 번째 방법은 HTML 방법을 사용하고 여기서는 DHTML 방법입니다. 후자의 스크립트 구문 분석 엔진은 더 이상 익명 메서드를 생성하지 않습니다.

4. 클래스 정의에 다음 키워드를 사용하세요.

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으로 문의하세요.