Was ist dies in einer Punkt-für-Punkt-Reihe von JavaScript?

Was ist dies in einer Punkt-für-Punkt-Reihe von JavaScript?

Verstehe das

Vielleicht haben Sie this in anderen objektorientierten Programmiersprachen gesehen und wissen, dass es sich auf ein von einem Konstruktor erstelltes Objekt bezieht. Tatsächlich stellt this in JavaScript aber mehr als nur das erstellte Objekt dar.

Schauen wir uns zunächst die Definition hierfür in der ECMAScript-Standardspezifikation an:

„Das Schlüsselwort this wird als Wert von ThisBinding des aktuellen Ausführungskontexts ausgewertet.“
„Dieses Schlüsselwort stellt den Wert von ThisBinding des aktuellen Ausführungskontexts dar.“

Schauen Sie sich dann die Definition von MDN hierzu an:

„In den meisten Fällen wird der Wert davon durch die Art und Weise bestimmt, wie eine Funktion aufgerufen wird.“
„In den meisten Fällen hängt der Wert davon ab, wie die Funktion aufgerufen wird.“

Nun, wenn Sie die beiden obigen Zeilen verstehen, müssen Sie nicht weiterlesen. Herzlichen Glückwunsch!

… das glaube ich nicht. Zumindest verstehe ich es noch immer nicht, wenn ich mir nur diese beiden Zeilen anschaue.

Schauen wir uns ein Beispiel an:

var getGender = Funktion() {
    gib people1.gender zurück;
};

var Leute1 = {
    Geschlecht Weiblich',
    getGender: getGender
};

var Leute2 = {
    Geschlecht: 'männlich',
    getGender: getGender
};

console.log(people1.getGender()); // weiblich
console.log(people2.getGender()); // weiblich

Was? Wieso hat people2 sein Geschlecht geändert? Das ist nicht das Ergebnis, das ich will. Warum?

Da getGender() people1.gender zurückgibt, ist das Ergebnis natürlich „weiblich“.

Wenn wir also getGender leicht ändern:

var getGender = Funktion() {
    gib dieses Geschlecht zurück;
};

An diesem Punkt sollten Sie zwei Ergebnisse erhalten: female und male .

Um also auf den zuvor erwähnten Punkt zurückzukommen: Anhand dieses Beispiels können wir erkennen, dass die Ausführungsergebnisse unterschiedlich sind, weil die aufgerufenen Objekte unterschiedlich sind , auch wenn die getGender -Methoden von people1 und people2 auf dieselbe getGender-Funktion verweisen.

Jetzt kennen wir den ersten wichtigen Punkt: **this wird tatsächlich gebunden, wenn die Funktion aufgerufen wird, und worauf es zeigt, hängt ganz davon ab, wie die Funktion aufgerufen wird. **Wie kann man das unterscheiden?

Wer ist das

Nachdem Sie die obigen Beispiele gelesen haben, sind Sie immer noch verwirrt, nicht wahr? Als nächstes schauen wir uns die Auswirkungen verschiedener Aufrufmethoden auf diesen Wert an.

Fall 1: Globale Objekte und Aufruf normaler Funktionen

In der globalen Umgebung bezieht sich dies auf das globale Objekt, das im Browser das Fensterobjekt ist. Im folgenden Beispiel bezieht sich dies auf das globale Objekt, unabhängig davon, ob es sich im strengen Modus befindet oder nicht.

var x = 1

console.log(dieses.x) // 1
konsole.log(dies.x === x) // wahr
console.log(dies === Fenster) // wahr

Wenn eine normale Funktion in der globalen Umgebung, also im nicht strikten Modus, aufgerufen wird, bezieht sich this in der normalen Funktion auch auf das globale Objekt; im strikten Modus ist this undefiniert. ES5 fügt den strikten Modus hinzu, damit JavaScript in einer restriktiveren Umgebung ausgeführt wird. Um Sicherheitsrisiken auszuschließen, verhindert der strikte Modus, dass das Schlüsselwort this auf das globale Objekt verweist.

var x = 1

Funktion fn() {
    console.log(dieses); // Globales Fensterobjekt console.log(dieses.x); // 1
}

fn();

Nach Verwendung des strikten Modus:

"use strict" // Strikten Modus verwenden var x = 1

Funktion fn() {
    console.log(dies); // undefiniert
    console.log(this.x); // Meldet „Eigenschaft ‚x‘ von undefined kann nicht gelesen werden“, weil dies nicht definiert ist.
}

fn();

Fall 2: Aufruf als Objektmethode

Wir wissen, dass wir dieses neu erstellte Ding eine „ Eigenschaft “ nennen, wenn der Wert in einem Objekt ein primitiver Typ ist (zum Beispiel eine Zeichenfolge, eine Zahl, ein Boolescher Wert); wenn der Wert in dem Objekt eine Funktion ist, nennen wir dieses neu erstellte Ding eine „ Methode“ .

Wenn eine Funktion eine Methode eines Objekts ist und als Methode eines Objekts aufgerufen wird, zeigt dies in der Funktion auf das übergeordnete Objekt .

var x = 1
var obj = {
    x: 2,
    fn: Funktion() {
        konsole.log(dies);    
        konsole.log(dies.x);
    }
}

obj.fn()     

// obj.fn() druckt das Ergebnis aus;
// Objekt {x: 2, fn: Funktion}
// 2

var a = obj.fn
A()   

// a() gibt das Ergebnis aus:   
// Fenster globales Objekt // 1

Im obigen Beispiel führen wir obj.fn() direkt aus. Das übergeordnete Objekt der Funktion ist obj, daher zeigt dies auf obj und der Wert von this.x ist 2. Dann weisen wir zuerst die fn-Methode der Variable a zu. a wird in der globalen Umgebung ausgeführt, daher zeigt dies auf das globale Objekt Window und der Wert von this.x ist 1.

Schauen wir uns ein weiteres Beispiel an. Wenn eine Funktion von mehreren verschachtelten Objekten aufgerufen wird, worauf verweist dies dann?

var x = 1
var obj = {
  x: 2,
  und: {
    x: 3,
    fn: Funktion() {
      console.log(dies); // Objekt {x: 3, fn: Funktion}
      konsole.log(dieses.x); // 3
    }
  }
}

obj.y.fn();

Warum ist das Ergebnis nicht 2? In diesem Fall müssen Sie sich einen Satz merken: this zeigt immer auf das übergeordnete Objekt, das die Funktion direkt aufruft , also y. Das obige Beispiel führt tatsächlich den folgenden Code aus.

var y = {
  x: 3,
  fn: Funktion() {
    console.log(dies); // Objekt {x: 3, fn: Funktion}
    konsole.log(dieses.x); // 3
  }
}

var x = 1
var obj = {
  x: 2,
  j: j
}

obj.y.fn();

Objekte können verschachtelt werden, ebenso wie Funktionen. Ändert sich das, wenn Funktionen verschachtelt werden? Lassen Sie uns dies mit dem folgenden Code untersuchen.

var obj = {
    y: Funktion() {
        konsole.log(dies === obj); // wahr
        console.log(dies); // Objekt {y: Funktion}
        fn();

        Funktion fn() {
            konsole.log(dies === obj); // falsch
            console.log(dies); // Globales Fensterobjekt}
    }
}

obj.y();

In der Funktion y zeigt dies auf das übergeordnete Objekt obj, das es aufruft, was in Ordnung ist. Aber in der verschachtelten Funktion fn zeigt dies nicht auf obj. Eine verschachtelte Funktion erbt this nicht von der Funktion, die sie aufruft. Wenn eine verschachtelte Funktion als Funktion aufgerufen wird, zeigt ihr this-Wert im nicht strikten Modus auf das globale Objekt und ist im strikten Modus undefiniert. Daher führt das obige Beispiel tatsächlich den folgenden Code aus.

Funktion fn() {
    konsole.log(dies === obj); // falsch
    console.log(dies); // Globales Fensterobjekt}

var obj = {
    y: Funktion() {
        konsole.log(dies === obj); // wahr
        console.log(dies); // Objekt {y: Funktion}
        fn();
    }
}

obj.y();

Fall 3: Aufruf als Konstruktor

Wir können das neue Schlüsselwort verwenden, um über den Konstruktor ein Instanzobjekt zu generieren. An dieser Stelle bezieht sich dies auf das neue Objekt .

var x = 1;

Funktion Fn() {
 dies.x = 2;
    console.log(dies); // Fn {x: 2}
}

var obj = new Fn(); // binde obj im Fn(..)-Aufruf daran console.log(obj.x) // 2

Beim Aufruf Fn(..) mit new wird ein neues Objekt konstruiert und im Fn(..) -Aufruf daran gebunden (obj). Erwähnenswert ist auch, dass, wenn der Konstruktor einen Nicht-Referenztyp (Zeichenfolge, Zahl, Boolescher Wert, Null, undefiniert) zurückgibt, dieser immer noch auf das instanziierte neue Objekt verweist.

var x = 1

Funktion Fn() {
  dies.x = 2

  zurückkehren {
    x: 3
  }
}

var a = neue Fn()

console.log(ax) // 3

Da Fn() ein Objekt (Referenztyp) zurückgibt, wird hier auf das zurückgegebene Objekt verwiesen. Was passiert, wenn der Rückgabewert kein Referenztyp ist?

var x = 1

Funktion Fn() {
  dies.x = 2

  Rückgabe 3
}

var a = neue Fn()

console.log(ax) // 2

Fall 4: Aufrufe von Methoden zum Aufrufen und Anwenden

Wenn Sie ändern möchten, worauf sich dies bezieht, können Sie die Methode „call“ oder „apply“ verwenden. Ihr erster Parameter besteht darin, anzugeben, wohin this zeigt, wenn die Funktion ausgeführt wird . Wenn der erste Parameter nicht übergeben wird (der Parameter ist leer) oder null oder undefiniert übergeben wird, zeigt dies standardmäßig auf das globale Objekt (nicht strikter Modus) oder auf „undefiniert“ (strenger Modus).

var x = 1;

var obj = {
  x: 2
}

Funktion fn() {
    konsole.log(dies);
    konsole.log(dies.x);
}

fn.call(Objekt)
// Objekt {x: 2}
// 2

fn.apply(Objekt)     
// Objekt {x: 2}
// 2

fn.aufruf()         
// Fenster globales Objekt // 1

fn.apply(null)    
// Fenster globales Objekt // 1

fn.call(undefiniert)    
// Fenster globales Objekt // 1

Wenn Sie call und apply verwenden und der an this übergebene Wert kein Objekt ist, verwendet JavaScript den entsprechenden Konstruktor, um ihn in ein Objekt umzuwandeln. Wenn beispielsweise ein Zahlentyp übergeben wird, wird new Number() ausgeführt; wenn ein Stringtyp übergeben wird, wird new String() ausgeführt; wenn ein Boolean-Typ übergeben wird, wird die Operation new Boolean() ausgeführt.

Funktion fn() {
  Konsole.log(Objekt.Prototyp.toString.call(dies))
}

fn.call('Liebe') // [Objekt String]
fn.apply(1) // [Objektnummer]
fn.call(true) // [Objekt Boolean]

Der Unterschied zwischen „call“ und „apply“ besteht darin, dass der zweite und die nachfolgenden Parameter von „call“ eine Parameterliste sind, während der zweite Parameter von „apply“ ein Array ist. Sowohl Parameterlisten als auch Parameterarrays werden als Argumente der Funktion ausgeführt.

var x = 1

var obj = {
  x: 2
}

Funktion Summe(y, z) {
  konsole.log(dies.x + y + z)
}

Summe.call(obj, 3, 4) // 9
Summe.apply(obj, [3, 4]) // 9

Fall 5: Aufruf der Bind-Methode

Durch den Aufruf von f.bind(someObject) wird eine Funktion mit demselben Textkörper und Gültigkeitsbereich wie f erstellt, aber in dieser neuen Funktion zeigt das this der neuen Funktion dauerhaft auf das erste von bind übergebene Argument , unabhängig davon, wie die Funktion aufgerufen wird.

var x = 1

var obj1 = {
    x: 2
};
var obj2 = {
    x: 3
};

Funktion fn() {
    konsole.log(dies);
    konsole.log(dies.x);
};

var a = fn.bind(obj1);
var b = a.bind(obj2);

fn();
// Fenster globales Objekt // 1

A();
// Objekt {x: 2}
// 2

B();
// Objekt {x: 2}
// 2

a.Aufruf(obj2);
// Objekt {x: 2}
// 2

Obwohl wir im obigen Beispiel versuchen, den this-Zeiger der Funktion a neu zuzuweisen, zeigt er immer noch auf das Objekt, das vom ersten Bind übergeben wurde. Auch die Verwendung der call- oder apply-Methode kann diese Tatsache nicht ändern, d. h. er zeigt dauerhaft auf den ersten Parameter, der vom Bind übergeben wurde.

Fall 6: Dies zeigt auf in der Pfeilfunktion

Es ist erwähnenswert, dass seit ES6 Pfeilfunktionen hinzugefügt wurden. Werfen wir einen Blick auf die Beschreibung der Pfeilfunktionen auf MDN.

Ein Pfeilfunktionsausdruck hat eine kürzere Syntax als ein Funktionsausdruck und bindet nicht seine eigenen this , arguments , super oder new.target . Pfeilfunktionen sind immer anonym. Diese Funktionsausdrücke eignen sich am besten für Nicht-Methodenfunktionen und können nicht als Konstruktoren verwendet werden.

Hier wurde klargestellt, dass Pfeilfunktionen keine eigene this Bindung haben. this ist tatsächlich this in der Funktion oder dem Funktionsausdruck, der es direkt enthält . Im vorherigen Beispiel verschachtelter Funktionen im Fall 2 erbt die verschachtelte Funktion nicht das this der übergeordneten Funktion. Welche Änderungen ergeben sich, wenn Pfeilfunktionen verwendet werden?

var obj = {
  y: Funktion() {
        konsole.log(dies === obj); // wahr
        console.log(dies); // Objekt {y: Funktion}

      var fn = () => {
          konsole.log(dies === obj); // wahr
          console.log(dies); // Objekt {y: Funktion}
      }
      fn();
  }
}

obj.y()

Im Gegensatz zu gewöhnlichen Funktionen zeigt this in der Pfeilfunktion auf obj. Dies liegt daran, dass es this von der Funktion in der vorherigen Ebene erbt. Sie können verstehen, dass die Pfeilfunktion die Richtung von this korrigiert. Daher wird das this der Pfeilfunktion nicht beim Aufruf bestimmt, sondern das Objekt, in dem sie sich bei der Definition befindet, ist ihr this .

Mit anderen Worten, das this der Pfeilfunktion hängt davon ab, ob es in der äußeren Schicht eine Funktion gibt. Wenn ja, ist das this der äußeren Funktion das this der inneren Pfeilfunktion. Wenn nicht, ist dies window .

var obj = {
  y: () => {
        konsole.log(dies === obj); // falsch
        console.log(dies); // Globales Fensterobjekt var fn = () => {
          konsole.log(dies === obj); // falsch
          console.log(dies); // Globales Fensterobjekt}
      fn();
  }
}

obj.y()

Obwohl im obigen Beispiel zwei Pfeilfunktionen vorhanden sind, hängt dies tatsächlich von der äußersten Pfeilfunktion ab. Da obj ein Objekt und keine Funktion ist, verweist dies auf das globale Objekt Window.

Wie Bind sind auch Pfeilfunktionen sehr „stur“. Wir können die Richtung hier nicht durch Call und Apply ändern, das heißt, der erste übergebene Parameter wird ignoriert .

var x = 1
var obj = {
    x: 2
}

var a = () => {
    konsole.log(dieses.x)
    console.log(dies)
}

a.call(Objekt)       
// 1
// Globales Fensterobjekt a.apply(obj)      
// 1
// Globales Fensterobjekt

Die obige Beschreibung ist aufgrund des vielen Textes vielleicht etwas trocken, deshalb schauen wir uns das folgende Flussdiagramm an. Ich denke, dieses Diagramm fasst es sehr gut zusammen. Der Prozess im Diagramm gilt nur für eine einzige Regel.

Zusammenfassung

Dieser Artikel stellt mehrere Situationen vor, auf die dies hinweist. Unterschiedliche Betriebsumgebungen und Aufrufmethoden wirken sich darauf aus. Im Allgemeinen hängt die Referenz des „This“ einer Funktion von dem Objekt ab, das die Funktion aktuell aufruft, also dem Objekt zum Zeitpunkt der Ausführung. In diesem Abschnitt müssen Sie Folgendes beherrschen:

  • Dies bezieht sich auf das globale Objekt;
  • Der Unterschied zwischen diesem und dem strengen Modus besteht darin, dass es sich um einen nicht strengen Modus handelt.
  • Dies weist auf mehrere Situationen hin, wenn eine Funktion als Objektmethode aufgerufen wird.
  • Der Unterschied zwischen dem, worauf dies bei Verwendung als Konstruktor verweist, und ob es zurückgibt;
  • Verwenden Sie „Call“ und „Apply“, um das Objekt zu ändern, das die Funktion aufruft.
  • Der Verweis darauf in der von Bind erstellten Funktion;
  • Der this-Zeiger in der Pfeilfunktion.

Damit ist der Artikel „Was ist das?“ in der JavaScript-Durchbruchsserie abgeschlossen. Weitere relevante JavaScript-Inhalte finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder durchsuchen Sie die verwandten Artikel weiter unten. Ich hoffe, Sie werden 123WORDPRESS.COM auch in Zukunft unterstützen!

Das könnte Sie auch interessieren:
  • Detaillierte Erklärung dieser Referenz und benutzerdefinierter Eigenschaften in JavaScript
  • Detaillierte Erklärung des this-Zeigeproblems in JavaScript
  • Detaillierte Erklärung der Funktionsklassifizierung und Beispiele für diese Zeigerfunktion in Javascript
  • Detaillierte Erklärung dieses Zeigeproblems in der JavaScript-Funktion
  • Detaillierte Erklärung dieses Zeigeproblems in JavaScript
  • Warum gibt es das in JS?

<<:  Zweistündiges Docker-Einführungstutorial

>>:  MySQL implementiert Beispielcode, um doppelte Hinzufügungen beim Hinzufügen eines Einkaufswagens zu verhindern

Artikel empfehlen

So begrenzen Sie die Anzahl gleichzeitiger Verbindungsanforderungen in Nginx

Einführung Das Modul, das die Anzahl gleichzeitig...

Informationen zur Nginx-GZIP-Konfiguration

Das Prinzip von nginx zur Erzielung einer Ressour...

Beispiel für die Implementierung einer eingebetteten Tabelle mit vue+elementUI

Während meines Praktikums im letzten Studienjahr ...

So erstellen Sie geplante Aufgaben mit dem Crond-Tool in Linux

Vorwort Crond ist ein Tool zur geplanten Ausführu...

Lösung für das Fehlen der my.ini-Datei in MySQL 5.7

Was ist my.ini? my.ini ist die in der MySQL-Daten...

Verwendung von TypeScript-Generics

Inhaltsverzeichnis 1. Einfach zu bedienen 2. Verw...

Beispiel für eine automatische Importmethode für das Vue3.0-Routing

1. Voraussetzungen Wir verwenden zum Importieren ...

Ein Leistungsfehler bei MySQL-Partitionstabellen

Inhaltsverzeichnis 2. Stapelanalyse mit pt-pmap 3...

vue-table implementiert das Hinzufügen und Löschen

In diesem Artikelbeispiel wird der spezifische Co...

JavaScript zum Erzielen eines dynamischen Tabelleneffekts

In diesem Artikel wird der spezifische Code für J...