In einer JavaScript-Datei habe ich gesehen:
function Somefunction(){
var that = this;
...
}
Was ist der Zweck that
, this
dies zu deklarieren und zuzuweisen ?
In einer JavaScript-Datei habe ich gesehen:
function Somefunction(){
var that = this;
...
}
Was ist der Zweck that
, this
dies 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 this
hä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 that
können Sie weiterhin auf den ursprünglichen Wert von zugreifen this
.
Persönlich mag ich die Verwendung that
als 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 that
scheint zu implizieren, dass die Variable alles ist, ABER this
.
forEach
Funktion 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 = this
mit 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
that
Variable in seinem Beispiel überhaupt nicht verwendet wird. Es sieht so aus, als würde das Erstellen einer Variablen this
den 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 this
automatisch auf den globalen Bereich gesetzt. Dies kann verwirrend sein, da Sie this
denselben 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.start
erstellen (wie im Beispiel) und dann eine Funktion innerhalb dieser Methode erstellen (wie im Beispiel activateStarter
). In der obersten Ebene zeigt die Methode this
auf das Objekt, es ist eine Methode von (in diesem Fall car
), aber in der inneren Funktion zeigt sie this
jetzt 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 that
verwendet. 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 that
ist 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 this
kann 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 that
wir dann auf die name-Eigenschaft innerhalb der sayHi
Methode von zugreifen könnenthat
, sodass diese ohne Probleme innerhalb des DOM-Aufrufs aufgerufen werden kann.
Eine andere Lösung besteht darin, ein leeres that
Objekt zuzuweisen , ihm Eigenschaften und Methoden hinzuzufügen und es dann zurückzugeben. Aber mit dieser Lösung haben Sie prototype
den 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.