In einer JavaScript-Datei habe ich gesehen:
function Somefunction(){
var that = this;
...
}
Was ist der Zweck that, thisdies zu deklarieren und zuzuweisen ?
In einer JavaScript-Datei habe ich gesehen:
function Somefunction(){
var that = this;
...
}
Was ist der Zweck that, thisdies zu deklarieren und zuzuweisen ?
Antworten:
Ich werde diese Antwort mit einer Illustration beginnen:
var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
// this is a reference to the element clicked on
var that = this;
colours.forEach(function() {
// this is undefined
// that is a reference to the element clicked on
});
});
Meine Antwort hat dies ursprünglich mit jQuery gezeigt, was sich nur geringfügig unterscheidet:
$('#element').click(function(){
// this is a reference to the element clicked on
var that = this;
$('.elements').each(function(){
// this is a reference to the current element in the loop
// that is still a reference to the element clicked on
});
});
Da sich thishäufig Änderungen ergeben, wenn Sie den Bereich durch Aufrufen einer neuen Funktion ändern, können Sie mit dieser Funktion nicht auf den ursprünglichen Wert zugreifen. Durch Aliasing auf thatkönnen Sie weiterhin auf den ursprünglichen Wert von zugreifen this.
Persönlich mag ich die Verwendung thatals Alias nicht. Es ist selten offensichtlich, worauf es sich bezieht, insbesondere wenn die Funktionen länger als ein paar Zeilen sind. Ich verwende immer einen aussagekräftigeren Alias. In meinen obigen Beispielen würde ich wahrscheinlich verwenden clickedEl.
var self = this;. Das Wort thatscheint zu implizieren, dass die Variable alles ist, ABER this.
forEachFunktion benötigt ein zweites optionales Argument, nämlich die Bindung der Funktion. colours.forEach(function(){/* 'this' is bound correctly --> */}, this);Daher sollte eine Notiz hinzugefügt werden, die var that = thismit nicht wirklich benötigt wird forEach.
Von Crockford
Konventionell machen wir diese Variable privat . Dies wird verwendet, um das Objekt für die privaten Methoden verfügbar zu machen. Dies ist eine Problemumgehung für einen Fehler in der ECMAScript-Sprachspezifikation, der dazu führt, dass dieser für innere Funktionen falsch eingestellt wird.
function usesThis(name) {
this.myName = name;
function returnMe() {
return this; //scope is lost because of the inner function
}
return {
returnMe : returnMe
}
}
function usesThat(name) {
var that = this;
this.myName = name;
function returnMe() {
return that; //scope is baked in with 'that' to the "class"
}
return {
returnMe : returnMe
}
}
var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' +
"UsesThis thinks it's called " + usesthis.returnMe().myName);
Dies warnt ...
UsesThat denkt, es heißt Dave
UsesThis denkt, es heißt undefiniert
thatVariable in seinem Beispiel überhaupt nicht verwendet wird. Es sieht so aus, als würde das Erstellen einer Variablen thisden Rest des Codes beeinflussen.
Dies ist ein Hack, um innere Funktionen (Funktionen, die in anderen Funktionen definiert sind) besser funktionieren zu lassen, als sie sollten. Wenn Sie in Javascript eine Funktion in einer anderen definieren, wird diese thisautomatisch auf den globalen Bereich gesetzt. Dies kann verwirrend sein, da Sie thisdenselben Wert wie in der äußeren Funktion erwarten .
var car = {};
car.starter = {};
car.start = function(){
var that = this;
// you can access car.starter inside this method with 'this'
this.starter.active = false;
var activateStarter = function(){
// 'this' now points to the global scope
// 'this.starter' is undefined, so we use 'that' instead.
that.starter.active = true;
// you could also use car.starter, but using 'that' gives
// us more consistency and flexibility
};
activateStarter();
};
Dies ist insbesondere dann ein Problem, wenn Sie eine Funktion als Methode eines Objekts car.starterstellen (wie im Beispiel) und dann eine Funktion innerhalb dieser Methode erstellen (wie im Beispiel activateStarter). In der obersten Ebene zeigt die Methode thisauf das Objekt, es ist eine Methode von (in diesem Fall car), aber in der inneren Funktion zeigt sie thisjetzt auf den globalen Bereich. Das ist ein Schmerz.
Das Erstellen einer Variablen, die gemäß Konvention in beiden Bereichen verwendet werden soll, ist eine Lösung für dieses sehr allgemeine Problem mit Javascript (obwohl es auch in jquery-Funktionen nützlich ist). Aus diesem Grund wird der sehr allgemein klingende Name thatverwendet. Es ist eine leicht erkennbare Konvention zur Überwindung eines Sprachmangels.
Wie El Ronnoco andeutet, hält Douglas Crockford dies für eine gute Idee.
Die Verwendung von thatist nicht wirklich erforderlich, wenn Sie eine Problemumgehung mit der Verwendung von call()oder durchführen apply():
var car = {};
car.starter = {};
car.start = function(){
this.starter.active = false;
var activateStarter = function(){
// 'this' now points to our main object
this.starter.active = true;
};
activateStarter.apply(this);
};
Manchmal thiskann auf einen anderen Bereich und auf etwas anderes verwiesen werden. Nehmen wir beispielsweise an, Sie möchten in diesem Fall eine Konstruktormethode innerhalb eines DOM-Ereignisses aufrufenthis bezieht sich dies auf das DOM-Element und nicht auf das erstellte Objekt.
HTML
<button id="button">Alert Name</button>
JS
var Person = function(name) {
this.name = name;
var that = this;
this.sayHi = function() {
alert(that.name);
};
};
var ahmad = new Person('Ahmad');
var element = document.getElementById('button');
element.addEventListener('click', ahmad.sayHi); // => Ahmad
Die obige Lösung geht davon aus this, dass thatwir dann auf die name-Eigenschaft innerhalb der sayHiMethode von zugreifen könnenthat , sodass diese ohne Probleme innerhalb des DOM-Aufrufs aufgerufen werden kann.
Eine andere Lösung besteht darin, ein leeres thatObjekt zuzuweisen , ihm Eigenschaften und Methoden hinzuzufügen und es dann zurückzugeben. Aber mit dieser Lösung haben Sie prototypeden Konstruktor verloren.
var Person = function(name) {
var that = {};
that.name = name;
that.sayHi = function() {
alert(that.name);
};
return that;
};
Hier ist ein Beispiel `
$(document).ready(function() {
var lastItem = null;
$(".our-work-group > p > a").click(function(e) {
e.preventDefault();
var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
if (item == lastItem) {
lastItem = null;
$('.our-work-single-page').show();
} else {
lastItem = item;
$('.our-work-single-page').each(function() {
var imgAlt = $(this).find('img').attr('alt'); //Here value of "this" is '.our-work-single-page'.
if (imgAlt != item) {
$(this).hide();
} else {
$(this).show();
}
});
}
});
});`
Sie können also sehen, dass dieser Wert zwei verschiedene Werte ist, abhängig von dem DOM-Element, auf das Sie abzielen. Wenn Sie jedoch "das" zum obigen Code hinzufügen, ändern Sie den Wert von "this", auf das Sie abzielen.
`$(document).ready(function() {
var lastItem = null;
$(".our-work-group > p > a").click(function(e) {
e.preventDefault();
var item = $(this).html(); //Here value of "this" is ".our-work-group > p > a"
if (item == lastItem) {
lastItem = null;
var that = this;
$('.our-work-single-page').show();
} else {
lastItem = item;
$('.our-work-single-page').each(function() {
***$(that).css("background-color", "#ffe700");*** //Here value of "that" is ".our-work-group > p > a"....
var imgAlt = $(this).find('img').attr('alt');
if (imgAlt != item) {
$(this).hide();
} else {
$(this).show();
}
});
}
});
});`
..... $ (that) .css ("Hintergrundfarbe", "# ffe700"); // Hier ist der Wert von "that" ".our-work-group> p> a", weil der Wert von var that = this; Obwohl wir uns bei "this" = ".our-work-single-page" befinden, können wir "that" dennoch verwenden, um das vorherige DOM-Element zu manipulieren.