Was liegt dieser JavaScript-Sprache zugrunde: var self = this?

357

In der Quelle für WebKit HTML 5 SQL Storage Notes Demo wurde Folgendes angezeigt :

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

Der Autor verwendet selbst an einigen Stellen (die Funktion Körper) und diese an anderen Orten (die Leichen in der Liste der Argumente von Methoden definiert Funktionen). Was ist los? Jetzt, wo ich es einmal bemerkt habe, werde ich es überall sehen?

Thomas L Holaday
quelle
4
Dies ist eine JS-
Sprachfunktion
2
Mögliches Duplikat von: var self = this? .
DavidRR
Das Konzept von DIESEM wird hier explizit erklärt. scotch.io/@alZami/understanding-this-in-javascript
AL-zami
Relevantes Beispiel in dieser Antwort stackoverflow.com/a/20279485/5610569 (auf die Frage "Wie kann man thisinnerhalb eines Rückrufs auf das Richtige zugreifen ?")
FluxLemur

Antworten:

431

Siehe diesen Artikel auf alistapart.com . (Ed: Der Artikel wurde seit dem ursprünglichen Link aktualisiert)

selfwird verwendet, um einen Verweis auf das Original beizubehalten, thisauch wenn sich der Kontext ändert. Diese Technik wird häufig in Event-Handlern verwendet (insbesondere bei Verschlüssen).

Bearbeiten: Beachten Sie, dass die Verwendung selfjetzt nicht mehr empfohlen wird window.selfund möglicherweise Fehler verursacht, wenn Sie nicht vorsichtig sind.

Was Sie die Variable nennen, spielt keine besondere Rolle. var that = this;ist in Ordnung, aber der Name hat nichts Magisches.

In einem Kontext deklarierte Funktionen (z. B. Rückrufe, Abschlüsse) haben Zugriff auf die Variablen / Funktionen, die im selben Bereich oder darüber deklariert wurden.

Zum Beispiel ein einfacher Ereignisrückruf:

function MyConstructor(options) {
  let that = this;

  this.someprop = options.someprop || 'defaultprop';

  document.addEventListener('click', (event) => {
    alert(that.someprop);
  });
}

new MyConstructor({
  someprop: "Hello World"
});

Jonathan Fingland
quelle
Es scheint, dass der Artikel sich in die Verwendung vonvar that = this;
Bob Stein
@ BobStein Danke. Ich werde die Antwort entsprechend aktualisieren.
Jonathan Fingland
96

Ich denke, der Variablenname 'self' sollte nicht mehr auf diese Weise verwendet werden, da moderne Browser eine globale Variableself bereitstellen , die auf das globale Objekt eines normalen Fensters oder eines WebWorkers verweist.

Um Verwirrung und mögliche Konflikte zu vermeiden, können Sie schreiben var thiz = thisoder var that = thisstattdessen.

Duan Yao
quelle
43
Ich benutze normalerweise_this
Djheru
6
@djheru +1. so viel schöner als " that" (woran sich mein Gehirn nie gewöhnen wird).
o_o_o--
9
Ich fing an, "mich" zu
benutzen
3
Bis moderne Browser anfangen, eine globale Variable bereitzustellen - dies, das oder ich.
Beejor
10
Es ist absolut kein Problem, den Namen selfzu verwenden, solange Sie ihn als variable deklarieren. Er wird das Globale beschatten. Wenn Sie das vergessen varhätten, würde es natürlich auch mit keinem anderen Namen funktionieren.
Bergi
34

Ja, du wirst es überall sehen. Es ist oft that = this;.

Sehen Sie, wie selfin Funktionen verwendet wird, die von Ereignissen aufgerufen werden? Diese würden ihren eigenen Kontext haben, also selfwird verwendet, um das zu halten this, was hereinkam Note().

Der Grund self, der den Funktionen weiterhin zur Verfügung steht, obwohl sie erst ausgeführt werden können, nachdem die Note()Funktion ausgeführt wurde, besteht darin, dass innere Funktionen aufgrund des Schließens den Kontext der äußeren Funktion erhalten .

Nosredna
quelle
12
Für mich ist der zwingende Punkt, dass dies selfkeine besondere Bedeutung hat. Ich persönlich bevorzuge es, eine Variable mit einem anderen Namen zu verwenden, als selfdies mich häufig verwirrt, da ich erwarte, dass 'Selbst' ein reserviertes Wort ist. Also ich mag deine Antwort. Und im Beispiel des OP würde ich es vorziehen var thisNote = thisoder ähnliches.
Steve
@steve stimmte zu, obwohl ich versuche, diese / Selbstreferenzen im Allgemeinen zu vermeiden, da sie in Bezug auf die Wartbarkeit sehr spröde sind.
MattLummus
28

Es sollte auch beachtet werden, dass es ein alternatives Proxy-Muster gibt, um einen Verweis auf das Original thisin einem Rückruf beizubehalten, wenn Sie das nicht mögenvar self = this Redewendung nicht .

Da eine Funktion mit einem bestimmten Kontext mithilfe von function.applyoder aufgerufen werden function.callkann, können Sie einen Wrapper schreiben, der eine Funktion zurückgibt, die Ihre Funktion mit applyoder unter callVerwendung des angegebenen Kontexts aufruft . proxyEine Implementierung dieses Musters finden Sie in der Funktion von jQuery . Hier ist ein Beispiel für die Verwendung:

var wrappedFunc = $.proxy(this.myFunc, this);

wrappedFunckann dann aufgerufen werden und hat Ihre Version thisals Kontext.

Max
quelle
10

Wie andere erklärt haben, var self = this;erlaubt Code in einem Abschluss auf den übergeordneten Bereich zurückgreifen.

Es ist jedoch jetzt 2018 und ES6 wird von allen gängigen Webbrowsern weitgehend unterstützt. Dasvar self = this; Redewendung ist nicht mehr so ​​wichtig wie früher.

Es ist jetzt möglich, var self = this;durch die Verwendung von Pfeilfunktionen zu vermeiden .

In Fällen, in denen wir verwendet hätten var self = this:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

Wir können jetzt eine Pfeilfunktion verwenden ohne var self = this:

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

Pfeilfunktionen haben keine eigenen thisund nehmen einfach den umschließenden Bereich an.

Elliot B.
quelle
Oder - Schock, Entsetzen! - Warum nicht die tatsächlich relevante Sache als Argument an Ihre Funktion übergeben (Abschluss)? Warum zum Teufel referenzieren Sie außerhalb des Gültigkeitsbereichs, warum zum Teufel programmiert jemand so? Es gibt nie einen wirklichen Grund dafür. Stattdessen haben .addEventListender("click", (x) => { console.log(x); });Sie das Wie und Warum sehr deutlich erklärt, und ich stimme zu, dass die Verwendung von Pfeilfunktionen sinnvoller ist, aber dennoch ... das ist einfach schrecklich, faul, chaotisch, Programmierung.
Benjamin R
2
In JavaScript ist es äußerst häufig und notwendig, auf den übergeordneten Bereich zurückzugreifen. Es ist ein grundlegender Teil der Sprache. Ihr Vorschlag, den übergeordneten Bereich als Argument für den Ereignishandler zu übergeben, ist eigentlich nicht möglich. Außerdem verwenden Pfeilfunktionen in ES6 das lexikalische Scoping - "dies" bezieht sich auf den aktuellen umgebenden Bereich und nicht weiter - es bezieht sich nicht auf den Status "außerhalb des Bereichs" oder ähnliches.
Elliot B.
9

Die Variable wird von den in der Methode definierten Inline-Funktionen erfasst. thisin der Funktion wird auf ein anderes Objekt verweisen. Auf diese Weise können Sie festlegen, dass die Funktion einen Verweis auf den thisim äußeren Bereich enthält.

Mehrdad Afshari
quelle
9

Es ist eine JavaScript-Eigenart. Wenn eine Funktion eine Eigenschaft eines Objekts ist, besser gesagt eine Methode, bezieht sich dies auf das Objekt. Im Beispiel eines Ereignishandlers ist das enthaltende Objekt das Element, das das Ereignis ausgelöst hat. Wenn eine Standardfunktion aufgerufen wird, dies wird auf das globale Objekt beziehen. Wenn Sie wie in Ihrem Beispiel verschachtelte Funktionen haben, bezieht sich dies überhaupt nicht auf den Kontext der äußeren Funktion. Innere Funktionen teilen den Gültigkeitsbereich mit der enthaltenen Funktion, sodass Entwickler Variationen von verwenden, var that = thisum das zu erhalten, was sie in der inneren Funktion benötigen.

kombat
quelle
5

Tatsächlich ist self ein Verweis auf window ( window.self), wenn Sie also sagen, dass var self = 'something'Sie einen Fensterverweis auf sich selbst überschreiben - weil self im Fensterobjekt existiert.

Dies ist , warum die meisten Entwickler bevorzugen var that = thisübervar self = this;

Wie auch immer; var that = this;Dies entspricht nicht der bewährten Vorgehensweise. Unter der Annahme, dass Ihr Code später von anderen Entwicklern überarbeitet / geändert wird, sollten Sie die gängigsten Programmierstandards in Bezug auf die Entwicklergemeinschaft verwenden

Daher sollten Sie so etwas wie var oldThis/ var oThis/ etc verwenden - um in Ihrem Bereich klar zu sein // ..ist nicht so viel, spart aber einige Sekunden und wenige Gehirnzyklen

SorinN
quelle
2
@prior Ich denke, es macht bis zum letzten Absatz Sinn.
Miphe
0

Wie oben mehrfach erwähnt, wird "Selbst" einfach verwendet, um vor dem Eintritt in die Funktion einen Verweis auf "dies" zu behalten. Einmal in der Funktion 'dies' bezieht sich auf etwas anderes.

Cyprien
quelle
@ JohnPaul ... das gibt eine Antwort. Es ist vielleicht nicht die richtige Antwort, aber wie können Sie sagen, dass "es ist gewohnt ..." keine Antwort auf "warum hat er das getan" ist?
GreenAsJade
-1
function Person(firstname, lastname) {
  this.firstname = firstname;

  this.lastname = lastname;
  this.getfullname = function () {
    return `${this.firstname}   ${this.lastname}`;
  };

  let that = this;
  this.sayHi = function() {
    console.log(`i am this , ${this.firstname}`);
    console.log(`i am that , ${that.firstname}`);
  };
}

let thisss = new Person('thatbetty', 'thatzhao');

let thatt = {firstname: 'thisbetty', lastname: 'thiszhao'};

thisss.sayHi.call (thatt);

ht zhao
quelle
1
Sie sollten mit Code eine Erklärung hinzufügen, was Sie speziell getan haben.
Farhana