Lassen Sie uns ausführlich über das Prinzip und die Implementierung von new in JS sprechen

Lassen Sie uns ausführlich über das Prinzip und die Implementierung von new in JS sprechen

Definition

Der neue Operator erstellt eine Instanz eines benutzerdefinierten Objekttyps oder eine Instanz eines integrierten Objekts mit einem Konstruktor.

Verwenden Sie die neue Methode [Konstruktor], um eine Objektinstanz zu erstellen. Unterschiede in den Konstruktoren führen jedoch dazu, dass unterschiedliche Instanzen erstellt werden.

Konstruktorkörper sind unterschiedlich

Ein Konstruktor ist auch eine Funktion. Der einzige Unterschied ist die aufrufende Methode. Jede Funktion, die mit dem neuen Operator aufgerufen wird, ist ein Konstruktor, und eine Funktion, die nicht mit dem neuen Operator aufgerufen wird, ist eine normale Funktion.

Der Konstruktor kann daher auch einen Rückgabewert haben, was jedoch zu anderen Ergebnissen für new führt.

Kein Rückgabewert

Funktion Person(Name) {
  dieser.name = Name;
}

let obj = neue Person("Jalenl");
konsole.log(obj);

Offensichtlich wird {name:'Jalenl'} gedruckt.

Rückgabeobjekt

Funktion Person(Alter) {
  dieses.Alter = Alter;
  return { Name: "Jalenl" };
}

let obj = neue Person(18);
konsole.log(obj);

Gedruckt wird {name:'Jalenl'}, was bedeutet, dass alle Definitionen vor der Rückgabe überschrieben werden. Was hier zurückgegeben wird, ist ein Objekt. Was ist, wenn es ein Basistyp ist?

Gibt Nicht-Objekte zurück

Funktion Person(Alter) {
  dieses.Alter = Alter;
  Rückgabe 1;
}

let obj = neue Person(18);
konsole.log(obj);

Gibt {age:21} zurück, was bedeutet, dass die Rückgabe ungültig ist und das Ergebnis dasselbe ist, als ob es keine Rückgabe gäbe. Was passiert, wenn dieses gebundene interne Attribut nicht vorhanden ist und der grundlegende Datentyp zurückgegeben wird?

Keine Eigenschaftsbindung + gibt Nicht-Objekt zurück

Funktion Person(){
    Rückgabe 1
}
neue Person()

Der zurückgegebene Wert ist wie erwartet ein leeres Objekt {}.

Zusammenfassend lässt sich sagen, dass das ursprüngliche Ergebnis nur geändert werden kann, wenn der Konstruktor einen Objekttyp zurückgibt.

Konstruktortypen sind unterschiedlich

Der Konstruktor ist eine normale Funktion

Die Spezifikation ECMA-262 3. Ausgabe beschreibt den Prozess zum Erstellen einer Objektinstanz:

13.2.2 [[Konstrukt]]
Wenn die Eigenschaft [[Construct]] für ein Funktionsobjekt F aufgerufen wird, werden die folgenden Schritte ausgeführt:

  1. Erstellen Sie ein neues natives ECMAScript-Objekt.
  2. Setzen Sie die [[Class]]-Eigenschaft von Result(1) auf "Object".
  3. Holen Sie sich den Wert der Prototypeigenschaft von F.
  4. Wenn Result(3) ein Objekt ist, setzen Sie die [[Prototype]]-Eigenschaft von Result(1) auf Result(3).
  5. Wenn Result(3) kein Objekt ist, setzen Sie die Eigenschaft [[Prototype]] von Result(1) auf das ursprüngliche Object-Prototypobjekt, wie in 15.2.3.1 beschrieben.
  6. Rufen Sie die [[Call]]-Eigenschaft von F auf, geben Sie Result(1) als diesen Wert an und geben Sie die an [[Construct]] übergebene Argumentliste als Argumentwerte an.
  7. Wenn Typ(Ergebnis(6)) ein Objekt ist, dann gibt Ergebnis(6) zurück.
  8. Ergebnis zurückgeben(1).

Um zusammenzufassen:

  1. Erstellen Sie ein neues Objekt im Speicher.
  2. Die Eigenschaft [[Prototype]] innerhalb dieses neuen Objekts wird der Prototype-Eigenschaft der Konstruktorfunktion zugewiesen.
  3. Dies wird innerhalb des Konstruktors dem neuen Objekt zugewiesen (d. h., dies zeigt auf das neue Objekt).
  4. Führen Sie den Code innerhalb des Konstruktors aus (fügen Sie dem neuen Objekt Eigenschaften hinzu).
  5. Wenn der Konstruktor ein Objekt zurückgibt, wird dieses Objekt zurückgegeben, andernfalls wird das neu erstellte Objekt (leeres Objekt) zurückgegeben.

Im fünften Schritt wurde bereits erklärt, warum unterschiedliche Konstruktoren zu unterschiedlichen neuen Ergebnissen führen.

Nachfolgend finden Sie eine Erklärung von MDN:

Wenn der Code new Foo(…) ausgeführt wird, passiert Folgendes:

  1. Es wird ein neues Objekt erstellt, das von Foo.prototype erbt.
  2. Ruft den Konstruktor Foo mit den angegebenen Argumenten auf und bindet diesen an das neu erstellte Objekt. new Foo ist gleichbedeutend mit new Foo(), d. h., es wird keine Argumentliste angegeben und Foo wird ohne Argumente aufgerufen.
  3. Das vom Konstruktor zurückgegebene Objekt ist das Ergebnis des neuen Ausdrucks. Wenn der Konstruktor nicht explizit ein Objekt zurückgibt, wird das in Schritt 1 erstellte Objekt verwendet. (Konstruktoren geben im Allgemeinen keine Werte zurück, aber Benutzer können sich dafür entscheiden, Objekte aktiv zurückzugeben, um die normalen Schritte zur Objekterstellung zu überschreiben.)

Der Konstruktor ist eine Pfeilfunktion

Wenn eine normale Funktion erstellt wird, erstellt die Engine gemäß bestimmten Regeln eine Prototypeigenschaft (die auf das Prototypobjekt verweist) für diese Funktion. Standardmäßig erhalten alle Prototypobjekte automatisch eine Eigenschaft namens „Konstruktor“, die auf den ihnen zugeordneten Konstruktor zurückverweist.

Funktion Person(){
    dieses.Alter = 18;
}
Person.Prototyp
/**
{
    Konstruktor: ƒ Foo()
    __proto__: Objekt
}
**/

Beim Erstellen einer Pfeilfunktion erstellt die Engine keine Prototypeigenschaft dafür. Die Pfeilfunktion hat keinen Konstruktor, den new aufrufen kann. Wenn Sie also new zum Aufrufen der Pfeilfunktion verwenden, tritt ein Fehler auf!

const Person = ()=>{}
new Person() // TypeError: Foo ist kein Konstruktor

Handschriftlich neu

Zusammenfassend lässt sich sagen, dass wir, nachdem wir uns mit dem Funktionsprinzip von new vertraut gemacht haben, eine Low-Profile-Version von new selbst implementieren können. Der Schlüssel zur Implementierung ist:

  1. Erlauben Sie Instanzen den Zugriff auf private Eigenschaften.
  2. Erlauben Sie Instanzen den Zugriff auf Eigenschaften in der Prototypkette, in der sich der Konstruktor-Prototyp (constructor.prototype) befindet.
  3. Das vom Konstruktor zurückgegebene Endergebnis ist ein Referenzdatentyp.
Funktion _new(Konstruktor, ...args) {
    // Konstruktortyp Rechtsurteil if(typeof Konstruktor !== 'Funktion') {
      throw new Error('Konstruktor muss eine Funktion sein');
    }
    //Erstellen Sie eine neue leere Objektinstanz let obj = new Object();
    // Binden Sie den Prototyp des Konstruktors an die neu erstellte Objektinstanz obj.__proto__ = Object.create(constructor.prototype);
    // Konstruktor aufrufen und Rückgabewert ermitteln let res = constructor.apply(obj, args);
    let isObject = typeof res === 'Objekt' und res !== null;
    let isFunction = Typ von res === 'Funktion';
    // Wenn ein Rückgabewert vorhanden ist und es sich um einen Objekttyp handelt, dann verwende ihn als Rückgabewert, andernfalls gib das zuvor erstellte Objekt zurück return isObject || isFunction ? res : obj;
};

Diese neue Low-Profile-Implementierung kann zum Erstellen von Instanzen benutzerdefinierter Klassen verwendet werden, unterstützt jedoch keine integrierten Objekte. Schließlich ist new ein Operator und die zugrunde liegende Implementierung ist komplizierter.

Zusammenfassen

Dies ist das Ende dieses Artikels über das Prinzip und die Implementierung von new in JS. Weitere relevante Inhalte zum Prinzip und zur Implementierung von new in JS finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Detaillierte Beschreibung der Funktion von new in JS
  • Detaillierte Erklärung des Prinzips und Beispiel des new-Operators in JavaScript
  • Untersuchung von zwei Möglichkeiten zur Implementierung von „new“ in JavaScript
  • So implementieren Sie den neuen Operator von JavaScript selbst
  • Detaillierte Erklärung der Rolle des neuen Operators in Js
  • Zusammenfassung gängiger Methoden von C# Newtonsoft.Json
  • C# Newtonsoft.Json analysiert mehrere verschachtelte JSON-Dateien für ein Deserialisierungsbeispiel
  • c#: Newtonsoft.Json-Paketvorgang hinzufügen
  • Der neue Befehl in JavaScript
  • Handschriftliche Implementierung von new in JS

<<:  CSS simuliert Float, um den Effekt eines zentrierten Textes zu erzielen, der das Bild links und rechts umgibt

>>:  Gestaltung von Popup-Fenstern und schwebenden Ebenen im Webdesign

Artikel empfehlen

JavaScript BOM-Standortobjekt + Navigatorobjekt + Verlaufsobjekt

Inhaltsverzeichnis 1. Standortobjekt 1. URL 2. Ei...

Einführung in die Anwendung der HTML-Tags superscript sup und subscript sub

HTML-Tag: hochgestellt In HTML definiert das <s...

Nginx-Anti-Crawler-Strategie, um UA am Crawlen von Websites zu hindern

Anti-Crawler-Richtliniendatei hinzugefügt: vim /u...

Zusammenfassung gängiger MySQL-Befehle

Festlegen des MySQL-Root-Passworts Melden Sie sic...

So überprüfen Sie die PCIe-Version und -Geschwindigkeit unter Linux

PCIE verfügt über vier verschiedene Spezifikation...

Detaillierter Prozess zur Implementierung des 2048-Minispiels im WeChat-Applet

Rendern Beispielcode Heute werden wir das WeChat-...

Die Verwendung des V-Modells in Vue3-Komponenten und ausführliche Erklärung

Inhaltsverzeichnis Verwenden Sie bidirektionale B...

So installieren und konfigurieren Sie WSL unter Windows

Was ist WSL Zitat aus der Baidu-Enzyklopädie: Das...

Vite+Electron zum schnellen Erstellen von VUE3-Desktopanwendungen

Inhaltsverzeichnis 1. Einleitung 2. Erstellen Sie...

Docker-Installations- und Konfigurationsschritte für MySQL

Inhaltsverzeichnis Vorwort Umfeld Installieren Er...

Tutorial zur Docker-Installation in einer Linux-Umgebung

1. Installationsumgebung Docker unterstützt die f...

MySQL verwendet SQL-Anweisungen zum Ändern von Tabellennamen

In MySQL können Sie die SQL-Anweisung „rename tab...