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

Spezifische Verwendung von Lazy Loading und Preloading in js

Verzögertes Laden (Lazy Loading) und Vorladen sin...

So erstellen Sie einen pptpd-Dienst in Alibaba Cloud Ubuntu 16.04

1. Um ein PPTP-VPN aufzubauen, müssen Sie Port 17...

Detaillierte Erläuterung des Ausführungsprinzips des MySQL-Kill-Befehls

Inhaltsverzeichnis Prinzip der Kill-Befehlsausfüh...

Detaillierte Erklärung der Verwendung von DECIMAL im MySQL-Datentyp

Detaillierte Erklärung der Verwendung von DECIMAL...

Detaillierte Erläuterung der FTP-Umgebungskonfigurationslösung (vsftpd)

1. Installieren Sie die vsftpd-Komponente Install...

Detaillierte Erklärung, wie Sie alle untergeordneten Elemente mit CSS auswählen

Wie wähle ich mit CSS rekursiv alle untergeordnet...

Lösung zum Vergessen des MySQL-Passworts unter Linux

Das Problem ist folgendes: Ich habe den Befehl my...

Auszeichnungssprache - Anker

Zurück: Markup Language - Phrasenelemente Original...

Docker startet im Status „Beendet“

Nach dem Docker-Lauf ist der Status immer „Beende...

MySQL-Optimierung: So schreiben Sie hochwertige SQL-Anweisungen

Vorwort Im Internet gibt es zahlreiche Informatio...

Installationshinweise zur komprimierten Version von MySQL 5.7.17

In diesem Artikel werden die Installationsschritt...

So installieren und verwenden Sie Cockpit unter CentOS 8/RHEL 8

Cockpit ist ein webbasiertes Serververwaltungstoo...