Dieser Artikel befasst sich nur mit diesem Thema. Wenn die Leser die Frage „Was ist das in JavaScript“ richtig beantworten können, bin ich der Meinung, dass es sich lohnt, einen solchen Artikel zu schreiben.
Wir müssen uns einen Satz merken: dieser zeigt immer auf das Objekt, auf dem die Funktion ausgeführt wird! und nicht das Objekt, in dem die Funktion erstellt wurde. Das heißt: Wer ruft, zeigt auf wen. Denken Sie daran...
In diesem Artikel wird analysiert, wo sich dieses Objekt in drei Situationen befindet.
1. Dies
in gewöhnlichen Funktionen
Egal wo sich dieser befindet, die erste Priorität besteht darin, den Standort zu finden, wenn die Funktion ausgeführt wird.
var name="全局"; function getName(){ var name="局部"; return this.name; }; alert(getName());
Wenn dies in der Funktion getName der globalen Umgebung erscheint, ist der Laufzeitort der Funktion getName
alert(getName());
Offensichtlich ist das Objekt, in dem sich die Funktion getName befindet, das globale Objekt, also das Fenster, daher muss sich die Heimat davon im Fenster befinden. Zu diesem Zeitpunkt zeigt dies auf das Fensterobjekt, sodass der von getName zurückgegebene this.name tatsächlich window.name ist, sodass die Warnung als „global“ ausgegeben wird!
Wenn dies also nicht in der Funktion der globalen Umgebung erscheint, sondern in der Funktion der lokalen Umgebung, wohin wird es fallen?
var name="全局"; var xpg={ name:"局部", getName:function(){ return this.name; } }; alert(xpg.getName());
Die Funktion getName, in der sich dies befindet, befindet sich nicht in der globalen Umgebung, sondern in der xpg-Umgebung. Unabhängig davon, wo sich dies befindet, müssen Sie den Speicherort finden, wenn die Funktion ausgeführt wird. Die Position der Funktion getName, wenn sie zu diesem Zeitpunkt ausgeführt wird
alert(xpg.getName());
Offensichtlich ist das Objekt, in dem sich die Funktion getName befindet, xpg, daher muss sich die Heimat davon in xpg befinden, das heißt, es zeigt auf das xpg-Objekt. Dann ist der von getName zurückgegebene this.name tatsächlich xpg.name. Die Warnung wird also als „teilweise“ ausgegeben!
Geben Sie ein Beispiel zur Festigung:
var someone = { name: "Bob", showName: function(){ alert(this.name); } }; var other = { name: "Tom", showName: someone.showName } other.showName(); //Tom
Obwohl das Schlüsselwort this in someone.showName deklariert ist, ist es bei der Ausführung other.showName, sodass es auf das aktuelle Objekt der Funktion other.showName verweist, das other ist, sodass die letzte Warnung other.name ist.
2. Dies zum Abschluss
Der Abschluss ist ebenfalls ein Unruhestifter. Kurz gesagt: Der sogenannte Abschluss besteht darin, eine weitere Funktion innerhalb einer Funktion zu erstellen, und die interne Funktion greift auf externe Variablen zu.
Der verlorene Sohn ist mit dem groben Abschluss vermischt, was zeigt, dass es niemals Frieden geben wird!
var name="全局"; var xpg={ name:"局部", getName:function(){ return function(){ return this.name; }; } }; alert(xpg.getName()());
Zu diesem Zeitpunkt ist dies offensichtlich ein Problem. Es liegt tatsächlich an der anonymen Funktion in der getName-Funktion, und die anonyme Funktion ruft den Variablennamen auf und bildet so einen Abschluss, das heißt, dieser befindet sich im Abschluss.
Unabhängig davon, wo sich dies befindet, müssen Sie den Speicherort finden, wenn die Funktion ausgeführt wird. Derzeit kann es nicht anhand der Laufzeitposition der Funktion getName beurteilt werden, sondern anhand der Laufzeitposition der anonymen Funktion.
function (){ return this.name; };
Offensichtlich ist das Objekt, in dem sich die anonyme Funktion befindet, window, also muss sich die Heimat davon in window befinden, dann ist der von der anonymen Funktion zurückgegebene this.name tatsächlich window.name, also ist das, was aus der Warnung hervorgeht, das „global“!
Also, wie macht man das im XPG-Abschluss? –Cache dies
var name="全局"; var xpg={ name:"局部", getName:function(){ var that=this; return function(){ return that.name; }; } }; alert(xpg.getName()());
Definieren Sie that=this in der getName-Funktion. Zu diesem Zeitpunkt wird die getName-Funktion bei
ausgeführtalert(xpg.getName());
Dann zeigt dies auf das xpg-Objekt, sodass es auch auf das xpg-Objekt zeigt. Wenn that.name in der anonymen Funktion des Abschlusses zurückgegeben wird, ist der zu diesem Zeitpunkt zurückgegebene that.name tatsächlich xpg.name, sodass der „Local“ alarmiert werden kann!
3. Das neue Schlüsselwort erstellt ein neues Objekt
Dies im Konstruktor nach dem neuen Schlüsselwort zeigt auf das neue Objekt, das mit dem Konstruktor erstellt wurde:
function Person(__name){ this.name = __name; //这个this指向用该构造函数构造的新对象,这个例子是Bob对象 } Person.prototype.show = function(){ alert(this.name); //this 指向Person,this.name = Person.name; } var Bob = new Person("Bob"); Bob.show(); //Bob
4. Rufen Sie dies an und bewerben Sie sich
Die einzigen Methoden, die dies in JavaScript verwalten können, sind „Call“ und „Apply“.
Anrufen und Bewerben sind wie die Eltern von diesem, sie werden dort leben, wo sie es leben lassen, und sie müssen gehorchen! Wenn keine Parameter vorhanden sind, ist das aktuelle Objekt window
var name="全局"; var xpg={ name:"局部" }; function getName(){ alert(this.name); } getName(xpg); getName.call(xpg); getName.call();
Wo das in der Funktion getName steht. Unabhängig davon, wo sich dies befindet, müssen Sie den Speicherort finden, wenn die Funktion ausgeführt wird. Die Position der Funktion getName, wenn sie zu diesem Zeitpunkt ausgeführt wird
getName(xpg);
Offensichtlich ist das Objekt, in dem sich die Funktion getName befindet, das Fenster, daher muss sich die Heimat dieses Objekts im Fenster befinden, das auf das Fensterobjekt zeigt. Dann ist der von getName zurückgegebene this.name tatsächlich window.name. die Warnung erscheint also als „global“!
Dann ist es Zeit anzurufen und sich zu bewerben, denn dieser muss auf sein Kommando hören!
getName.call(xpg);
Unter diesen gibt der Aufruf an, dass die Heimat davon das xpg-Objekt ist, da dieses nur in xpg festgelegt werden muss. Dann zeigt dies zu diesem Zeitpunkt auf das xpg-Objekt, und this.name ist tatsächlich xpg.name, sodass die Warnung ausgegeben wird als „lokal“ !
5. Dies in der Bewertung
Für die Eval-Funktion scheint das aktuelle Objekt bei der Ausführung nicht angegeben zu sein, aber tatsächlich zeigt dies nicht auf das Fenster, da der Bereich bei der Ausführung der Funktion dem aktuellen Bereich entspricht, was äquivalent ist zum Ausfüllen des Codes in dieser Zeile. Das folgende Beispiel veranschaulicht dieses Problem:
var name = "window"; var Bob = { name: "Bob", showName: function(){ eval("alert(this.name)"); } }; Bob.showName(); //Bob
6、没有明确的当前对象时的this
当没有明确的执行时的当前对象时,this指向全局对象window。
例如对于全局变量引用的函数上我们有:
var name = "Tom"; var Bob = { name: "Bob", show: function(){ alert(this.name); } } var show = Bob.show; show(); //Tom
你可能也能理解成show是window对象下的方法,所以执行时的当前对象时window。但局部变量引用的函数上,却无法这么解释:
var name = "window"; var Bob = { name: "Bob", showName: function(){ alert(this.name); } }; var Tom = { name: "Tom", showName: function(){ var fun = Bob.showName; fun(); } }; Tom.showName(); //window
在浏览器中setTimeout、setInterval和匿名函数执行时的当前对象是全局对象window,这条我们可以看成是上一条的一个特殊情况。
var name = "Bob"; var nameObj ={ name : "Tom", showName : function(){ alert(this.name); }, waitShowName : function(){ setTimeout(this.showName, 1000); } }; nameObj.waitShowName();
所以在运行this.showName的时候,this指向了window,所以最后显示了window.name。
7、dom事件中的this
(1)你可以直接在dom元素中使用
<input id="btnTest" type="button" value="提交" onclick="alert(this.value))" />
分析:对于dom元素的一个onclick(或其他如onblur等)属性,它为所属的html元素所拥有,直接在它触发的函数里写this,this应该指向该html元素。
(2)给dom元素注册js函数
a、不正确的方式
<script type="text/javascript"> function thisTest(){ alert(this.value); // 弹出undefined, this在这里指向?? } </script> <input id="btnTest" type="button" value="提交" onclick="thisTest()" />
分析:onclick事件直接调用thisTest函数,程序就会弹出undefined。因为thisTest函数是在window对象中定义的,
所以thisTest的拥有者(作用域)是window,thisTest的this也是window。而window是没有value属性的,所以就报错了。
b、正确的方式
<input id="btnTest" type="button" value="提交" /> <script type="text/javascript"> function thisTest(){ alert(this.value); } document.getElementById("btnTest").onclick=thisTest; //给button的onclick事件注册一个函数 </script>
分析:在前面的示例中,thisTest函数定义在全局作用域(这里就是window对象),所以this指代的是当前的window对象。而通过document.getElementById(“btnTest”).onclick=thisTest;这样的形式,其实是将btnTest的onclick属性设置为thisTest函数的一个副本,在btnTest的onclick属性的函数作用域内,this归btnTest所有,this也就指向了btnTest。其实如果有多个dom元素要注册该事件,我们可以利用不同的dom元素id,用下面的方式实现:
document.getElementById("domID").onclick=thisTest; //给button的onclick事件注册一个函数。
因为多个不同的HTML元素虽然创建了不同的函数副本,但每个副本的拥有者都是相对应的HTML元素,各自的this也都指向它们的拥有者,不会造成混乱。
为了验证上述说法,我们改进一下代码,让button直接弹出它们对应的触发函数:
<input id="btnTest1" type="button" value="提交1" onclick="thisTest()" /> <input id="btnTest2" type="button" value="提交2" /> <script type="text/javascript"> function thisTest(){ this.value="提交中"; } var btn=document.getElementById("btnTest1"); alert(btn.onclick); //第一个按钮函数 var btnOther=document.getElementById("btnTest2"); btnOther.onclick=thisTest; alert(btnOther.onclick); //第二个按钮函数 </script> 其弹出的结果是: //第一个按钮 function onclick(){ thisTest() } //第二个按钮 function thisTest(){ this.value="提交中"; }
从上面的结果你一定理解的更透彻了。
By the way,每新建一个函数的副本,程序就会为这个函数副本分配一定的内存。而实际应用中,大多数函数并不一定会被调用,于是这部分内存就被白白浪费了。所以我们通常都这么写:
<input id="btnTest1" type="button" value="提交1" onclick="thisTest(this)" /> <input id="btnTest2" type="button" value="提交2" onclick="thisTest(this)" /> <input id="btnTest3" type="button" value="提交3" onclick="thisTest(this)" /> <input id="btnTest4" type="button" value="提交4" onclick="thisTest(this)" /> <script type="text/javascript"> function thisTest(obj){ alert(obj.value); } </script>
这是因为我们使用了函数引用的方式,程序就只会给函数的本体分配内存,而引用只分配指针。这样写一个函数,调用的地方给它分配一个(指针)引用,这样效率就高很多。当然,如果你觉得这样注册事件不能兼容多种浏览器,可以写下面的注册事件的通用脚本:
//js事件 添加 EventUtil.addEvent(dom元素,事件名称,事件触发的函数名) 移除EventUtil.removeEvent(dom元素,事件名称,事件触发的函数名) var EventUtil = new eventManager(); //js事件通用管理器 dom元素 添加或者移除事件 function eventManager() { //添加事件 //oDomElement:dom元素,如按钮,文本,document等; ****** oEventType:事件名称(如:click,如果是ie浏览器,自动将click转换为onclick);****** oFunc:事件触发的函数名 this.addEvent = function(oDomElement, oEventType, oFunc) { //ie if (oDomElement.attachEvent) { oDomElement.attachEvent("on" + oEventType, oFunc); } //ff,opera,safari等 else if (oDomElement.addEventListener) { oDomElement.addEventListener(oEventType, oFunc, false); } //其他 else { oDomElement["on" + oEventType] = oFunc; } } this.removeEvent = function(oDomElement, oEventType, oFunc) { //ie if (oDomElement.detachEvent) { oDomElement.detachEvent("on" + oEventType, oFunc); } //ff,opera,safari等 else if (oDomElement.removeEventListener) { oDomElement.removeEventListener(oEventType, oFunc, false); } //其他 else { oDomElement["on" + oEventType] = null; } } }
正像注释写的那样,要注册dom元素事件,用EventUtil.addEvent(dom元素,事件名称,事件触发的函数名)即可, 移除时可以这样写:EventUtil.removeEvent(dom元素,事件名称,事件触发的函数名),这是题外话,不说了。
以上就是本文的全部内容,希望通过这篇文章大家更加了解javascript的this关键字,大家共同进步。