JavaScript-Wissen: Konstruktoren sind auch Funktionen

JavaScript-Wissen: Konstruktoren sind auch Funktionen

Als erstes muss klargestellt werden, dass Konstruktoren auch Funktionen sind

Ich verwende häufig Konstruktoren, um Instanzobjekte zu erstellen. Beispielsweise kann die Instanziierung von Objekten und Arrays über die entsprechenden Konstruktoren Object () und Array () abgeschlossen werden.

Es gibt keinen Unterschied in der Syntaxdefinition zwischen Konstruktoren und normalen Funktionen. Die Hauptunterschiede spiegeln sich in den folgenden drei Punkten wider.

(1) Der erste Buchstabe des Konstruktorfunktionsnamens wird normalerweise groß geschrieben. Gemäß Konvention beginnen Konstruktornamen mit einem Großbuchstaben, während Nicht-Konstruktornamen mit einem Kleinbuchstaben beginnen. Dies ist objektorientierten Programmiersprachen entlehnt und hilft, Konstruktoren von normalen Funktionen in ECMAScript zu unterscheiden.

(2) Das Schlüsselwort this wird innerhalb des Funktionskörpers verwendet, um die zu erzeugende Objektinstanz anzugeben. Der Konstruktor gibt keinen expliziten Wert zurück, sondern gibt standardmäßig "this" zurück. Im folgenden Codeausschnitt verwendet die Funktion Person() nicht das Schlüsselwort return, um Informationen zurückzugeben, aber die Ausgabevariable person1 ist eine Person-Instanz mit den Attributwerten „Name“ und „Alter“.

<!DOCTYPE html>
<html lang="de">
<Kopf>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=Gerätebreite, Anfangsmaßstab=1.0">
  <title>Dokument</title>
</Kopf>
<Text>
  <Skript>
      //1. Definieren Sie die Konstruktorfunktion Person(name,age){
        dieses.Alter = Alter;
        dieser.name = Name;
        dies.sayName = Funktion(){
            konsole.log(dieser.name);
        } 
      }
      // 2. Instanzobjekt generieren var person1 = new Person('Xiao Su','18');
      // 3. Instanzobjekt drucken console.log(person1);
  </Skript>
</body>
</html>

Der Anzeigeeffekt ist wie folgt


(3) Wenn es als Konstruktor aufgerufen wird, muss es in Verbindung mit dem neuen Operator verwendet werden. Dies ist sehr wichtig. 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.

1. Definition und Aufruf des Konstruktors

Der Konstruktor wird auch als benutzerdefinierte Funktion bezeichnet, die Eigenschaften und Methoden für einen eigenen Objekttyp in Form einer Funktion definiert.

Beispiel:

<!DOCTYPE html>
<html lang="de">
<Kopf>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=Gerätebreite, Anfangsmaßstab=1.0">
  <title>Dokument</title>
</Kopf>
<Text>
  <Skript>
      //1. Definieren Sie die Konstruktorfunktion Person(name,age){
        dieses.Alter = Alter;
        dieser.name = Name;
        dies.sayName = function(){
            konsole.log(dieser.name);
        } 
      }
      // 2. Instanzobjekt generieren var person1 = new Person('Xiao Su','18');
      // 3. Rufen Sie die Methode person1.sayName() auf.
  </Skript>
</body>
</html>

2. Zweck des neuen Keywords

Wenn der Konstruktor ausgeführt wird, führt er die folgenden vier Schritte aus:

  • Durch das Erstellen eines Instanzobjekts mit dem neuen Schlüsselwort (Operator) wird eine neue Adresse im Speicher erstellt.
  • Bestimmen Sie im Konstruktor den Verweis hierauf auf die Instanz selbst.
  • Führen Sie den Konstruktorcode aus, um der Instanz Eigenschaften hinzuzufügen.
  • Gibt das neu erstellte Objekt zurück.

Nehmen Sie den vorherigen Code zum Generieren der Person1-Instanz als Beispiel.

Schritt 1: Erstellen Sie im Speicher eine neue Adresse für die Instanz „person1“.

Schritt 2: Stellen Sie fest, dass der this-Zeiger der person1-Instanz auf die Person selbst zeigt.

Schritt 3: Fügen Sie der Instanz „person1“ die Attribute „name“, „age“ und „sayName“ hinzu, wobei der Attributwert „sayName“ eine Funktion ist.

Schritt 4: Geben Sie die Instanz „person1“ zurück.

Ein Beispiel

var person1 = neue Person("Bob", 18);

Diese Codezeile entspricht

// Demonstriere die Funktion der neuen Funktion Person(name,age) {
  // 1. Erstellen Sie ein neues Objekt var instance = new Object();
  // 2. Richten Sie dies innerhalb der Funktion auf dieses neue Objekt. Dies = Instanz;
  // 3. Führen Sie den Code innerhalb des Konstruktors aus: this.name = name;
  dieses.Alter = Alter;
  dies.sayName = Funktion () {
    konsole.log(dieser.name);
  };
  // 4. Gib das neue Objekt als Rückgabewert zurück return instance;
}

Dies bedeutet, dass die Instanz der Person1 zugewiesen wird, das heißt, Person1 = Instanz. Tatsächlich ist es so:

// Demonstriere die Funktion der neuen Funktion Person(name,age) {
  // 1. Erstellen Sie ein neues Objekt var person1 = new Object();
  // 2. Richten Sie dies innerhalb der Funktion auf dieses neue Objekt: this = person1;
  // 3. Führen Sie den Code innerhalb des Konstruktors aus: this.name = name;
  dieses.Alter = Alter;
  dies.sayName = Funktion () {
    konsole.log(dieser.name);
  };
  // 4. Gib das neue Objekt als Rückgabewert zurück return person1;
}

3. Konstruktorproblem: Speicherverschwendung

Grundlegende Tatsache: Das sayName-Attribut ist in verschiedenen Instanzen unterschiedlich. Zum Beispiel:

<!DOCTYPE html>
<html lang="de">
<Kopf>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=Gerätebreite, Anfangsmaßstab=1.0">
  <title>Dokument</title>
</Kopf>
<Text>
  <Skript>
    // 1. Benutzerdefinierte Konstruktorfunktion Person(Name,Alter) {
      dieser.name = Name;
      dieses.Alter = Alter;
      // Der Wert der Type-Eigenschaft darin bleibt unverändert. this.type = "human";
      // Die sayName-Methode jedes Objekts ist gleich this.sayName = function () {
        konsole.log(dieser.name);
      };
    }
    
    var person1 = neue Person('Bob',18);
    var person2 = neue Person('Mike',20);
    // 2. Bestimmen Sie, ob die jeweiligen Methoden dieselbe Funktion sind console.log(person1.sayName === person2.sayName); // false
  </Skript>
</body>
</html>

Erläuterung: Mit der Methode console.log(person1.sayName === person2.sayName) kann ermittelt werden, ob die beiden Funktionen identisch sind. Offensichtlich handelt es sich nicht um dieselbe Funktion, sodass die beiden Funktionen zwei Speicherplätze belegen, was zu Speicherverschwendung führt.

Wie lösen wir also das Problem, dass Funktionen Speicher belegen? Die Antwort besteht darin, die internen Funktionen des Objekts als öffentliche Funktionen zu extrahieren

<!DOCTYPE html>
<html lang="de">
<Kopf>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=Gerätebreite, Anfangsmaßstab=1.0">
  <title>Dokument</title>
</Kopf>
<Text>
  <Skript>
    // Lösung 1: Extrahieren Sie die öffentlichen Funktionen aus der Konstruktorfunktion sayName() {
      konsole.log(dieser.name);
    }
    Funktion sayAge() {
      Konsole.log(dieses.Alter);
    }
    //1. Benutzerdefinierte Objektfunktion Person(Name,Alter) {
      dieser.name = Name;
      dieses.Alter = Alter;
      // Der Wert der Type-Eigenschaft darin bleibt unverändert. this.type = "human";
      // Die sayName-Methode jedes Objekts ist gleich this.sayName = sayName;
      dies.sayAge = sagAge;
    }
    //2. Instanziieren Sie das Objekt var person1 = new Person('Bob',18);
    var person2 = neue Person('Mike',20);
    console.log(person1.sayName === person2.sayName); // wahr
    </Skript>
</body>
</html>

An dieser Stelle gibt es auch ein Problem: Wenn mehrere öffentliche Funktionen vorhanden sind, müssen mehrere Funktionen extern erstellt werden, was zu Namenskonflikten führen kann.

Lösung: Mehrere allgemeine Funktionen in einem Objekt kapseln

<!DOCTYPE html>
<html lang="de">
<Kopf>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=Gerätebreite, Anfangsmaßstab=1.0">
  <title>Dokument</title>
</Kopf>
<Text>
  <Skript>
    // 3. Kapseln Sie mehrere öffentliche Funktionen in ein Objekt var fns = {
      sageName : Funktion () {
        konsole.log(dieser.name);
      },
      sageAlter : Funktion () {
        Konsole.log(dieses.Alter);
      }      
    };    
    // 1. Benutzerdefinierte Objektfunktion Person(Name,Alter) {
      dieser.name = Name;
      dieses.Alter = Alter;
      dieser.Typ = "Mensch";
      dies.sayName = fns.sayName;
      dies.sayAge = fns.sayAge;
    }
    // 2. Objektinstanz generieren var person1 = new Person("Bob",18);
    var person2 = neue Person("Mike",20);

    // person1.sayName();
    console.log(person1.sayName === person2.sayName);
    console.log(person1.sayAge === person2.sayAge);
  </Skript>
</body>
</html>

Erläuterung: Die Kapselung mehrerer Funktionen in einem Objekt kann das Problem möglicher Funktionsnamenkonflikte lösen.

Durch die Einrichtung einer global zugänglichen Funktion kann diese von allen Instanzen aus aufgerufen werden, ohne dass sie wiederholt erstellt werden muss.

Es gibt jedoch ein Problem. Wenn alle einem Objekt hinzugefügten Funktionen als globale Funktionen behandelt werden, ist es unmöglich, die Eigenschaftenkapselung eines Objekts vom Typ „Benutzerdefinierter Typ“ abzuschließen (was bedeutet, dass globale Funktionen nur Funktionen, aber keine Eigenschaften kapseln können, da Eigenschaften außerhalb der Funktion gekapselt werden und als globale Variablen definiert werden müssen, bevor sie aufgerufen werden können, was globale Variablen verunreinigt). Daher ist dies keine gute Lösung.

An dieser Stelle wird das Konzept des Prototyps eingeführt. Die Verwendung des Konzepts des Prototyps kann dieses Problem gut lösen.

Zusammenfassen

Dieser Artikel endet hier. Ich hoffe, er kann Ihnen helfen. Ich hoffe auch, dass Sie mehr Inhalten auf 123WORDPRESS.COM mehr Aufmerksamkeit schenken können!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung der Js-Klassenkonstruktion und Vererbungsfälle
  • Mehrere Implementierungsmethoden für die Vererbung von JavaScript-Klassen
  • Vererbungsdefinition und Verwendungsanalyse der js-Klasse
  • 15 Minuten, um ein tiefes Verständnis der JS-Vererbungsklassifizierung, -prinzipien und -verwendung zu erlangen
  • Wie gut kennen Sie sich mit dem Konstruktor, Prototyp, der Prototypenkette und Neuem von JavaScript aus?
  • JS Leicht verständliche Funktion und Konstruktor
  • Detaillierte Erklärung von Klassen, Vererbung und Konstruktoren in Javascript

<<:  Tutorial zur Implementierung der Zwei-Wege-Authentifizierung durch OpenSSL (mit Server- und Client-Code)

>>:  Implementieren einer verteilten Sperre mit MySQL

Artikel empfehlen

So kapseln Sie Timerkomponenten in Vue3

Hintergrund Wenn Sie auf manchen Webseiten von Ei...

So exportieren Sie die MySQL-Tabellenstruktur nach Excel

Die Voraussetzungen sind wie folgt Exportieren Si...

So stellen Sie ein SpringBoot-Projekt mit Docker bereit

Die Entwicklung der Docker-Technologie bietet ein...

Shell-Skripteinstellungen zum Verhindern von Brute-Force-SSH

Das Shell-Skript richtet die Zugriffskontrolle ei...

Diagramm des Datenübertragungsprozesses beim dritten TCP-Handshake

Die Prozesspakete mit dem SYN-Flag im RFC793-Doku...

Zusammenfassung der grundlegenden Verwendung des $-Symbols in Linux

Linux-Version: CentOS 7 [root@azfdbdfsdf230lqdg1b...

Implementierungsschritte zur Installation eines Redis-Containers in Docker

Inhaltsverzeichnis Redis auf Docker installieren ...

Vue implementiert Upload-Komponente

Inhaltsverzeichnis 1. Einleitung 2. Ideen Zwei Mö...