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('elmtp'); p.attachEvent('onclick', EventHandler); function EventHandler() { // 在此使用this } // --> pision element var p = document.getElementById('elmtp'); p.attachEvent('onclick', 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('elmtp'); p.onclick = function() { // 在此使用this }; / --> pision element var p = document.getElementById('elmtp'); p.onclick = function() { // 在此使用this }; // -->
여기서 this 키워드로 표시된 내용은 p 요소 개체 인스턴스입니다. DHTML을 사용하여 스크립트에서 p.onclick에 직접 할당합니다. .method는 p 개체 인스턴스에 멤버 메서드를 추가하는 것과 같습니다. 이 방법과 첫 번째 방법의 차이점은 첫 번째 방법은 HTML 방법을 사용하고 여기서는 DHTML 방법입니다. 후자의 스크립트 구문 분석 엔진은 더 이상 익명 메서드를 생성하지 않습니다.
4. 클래스 정의에 다음 키워드를 사용하세요.
function JSClass() { var myName = 'jsclass'; this.m_Name = 'JSClass'; } JSClass.prototype.ToString = function() { alert(myName + ', ' + this.m_Name); }; var jc = new JSClass(); jc.ToString(); function JSClass() { var myName = 'jsclass'; this.m_Name = 'JSClass'; } JSClass.prototype.ToString = function() { alert(myName + ', ' + 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('(')); fnName = fnName.replace(/^function/, ''); return fnName.replace(/(^\s+)|(\s+$)/g, ''); } function foo(){} alert(foo.GetName()); function.prototype.GetName = function() { var fnName = this.toString(); fnName = fnName.substr(0, fnName.indexOf('(')); fnName = fnName.replace(/^function/, ''); return fnName.replace(/(^\s+)|(\s+$)/g, ''); } function foo(){} alert(foo.GetName());
这里的this指代的是被添加原形的类的实例,和4中类定义有些相似,没有什么太特别的地方。
6、结合2&4,说一个比较迷惑的this关键字使用:
view plaincopy to clipboardprint? function JSClass() { this.m_Text = 'pision element'; this.m_Element = document.createElement('p'); this.m_Element.innerHTML = this.m_Text; this.m_Element.attachEvent('onclick', 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 = 'pision element'; this.m_Element = document.createElement('p'); this.m_Element.innerHTML = this.m_Text; this.m_Element.attachEvent('onclick', 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 = 'Outer Name'; function InnerFoo() { var Name = 'Inner Name'; alert(Name + ', ' + this.Name); } return InnerFoo; } OuterFoo()(); function OuterFoo() { this.Name = 'Outer Name'; function InnerFoo() { var Name = 'Inner Name'; alert(Name + ', ' + 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 = 'func member!'; //函数类的成员变量 this.m_Element = document.createElement('p'); //成员变量,创建一个p对象 this.m_Element.innerHTML = varText; //使用函数的普通变量 this.m_Element.attachEvent('onclick', this.ToString); //给这个对象的事件连上处理函数 this.newElement = document.createElement('p'); 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 = 'func member!'; //函数类的成员变量 this.m_Element = document.createElement('p'); //成员变量,创建一个p对象 this.m_Element.innerHTML = varText; //使用函数的普通变量 this.m_Element.attachEvent('onclick', this.ToString); //给这个对象的事件连上处理函数 this.newElement = document.createElement('p'); 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 중국어 웹사이트의 기타 관련 기사를 참조하세요!