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

Zusammenfassung der allgemeinen Bedienungskenntnisse der MySQL-Datenbank

Dieser Artikel fasst gängige Betriebstechniken fü...

vue3+ts+EsLint+Prettier Standardcode-Implementierung

Inhaltsverzeichnis verwenden Verwendung von EsLin...

Tipps zur MySQL-Leistungsoptimierung

MySQL-Leistungsoptimierung MySQL wird in Internet...

Ein magischer MySQL-Deadlock-Troubleshooting-Datensatz

Hintergrund Apropos MySQL-Deadlock: Ich habe bere...

Schritte für Docker zum Erstellen eines privaten Lagerhafens

Hafen Harbor ist eine Open-Source-Lösung zum Erst...

Detaillierte Installation und Verwendung von Docker-Compose

Docker Compose ist ein Docker-Tool zum Definieren...

Detaillierte Erklärung zur Verwendung von Element-Plus in Vue3

Inhaltsverzeichnis 1. Installation 2. Importieren...

Mybatis-Statistiken zur Ausführungszeit jeder SQL-Anweisung

Hintergrund In letzter Zeit werde ich in Intervie...

CSS3 Flexible Box Flex, um ein dreispaltiges Layout zu erreichen

Wie der Titel schon sagt: Die Höhe ist bekannt, d...