JavaScript verwendet prototypische Vererbung: Jedes Objekt erbt Eigenschaften und Methoden von seinem Prototypobjekt.

Die traditionelle Klasse als Blaupause zum Erstellen von Objekten, die in Sprachen wie Java oder Swift verwendet wird, existiert in JavaScript nicht. Die prototypische Vererbung befasst sich nur mit Objekten.

Die prototypische Vererbung kann die klassische Klassenvererbung emulieren. Um die traditionellen Klassen in JavaScript zu bringen, führt ES2015 standard die class Syntax ein: ein syntaktischer Zucker über die prototypische Vererbung.,

Dieser Beitrag macht Sie mit JavaScript-Klassen vertraut: Definieren einer Klasse, Initialisieren der Instanz, Definieren von Feldern und Methoden, Verstehen der privaten und öffentlichen Felder, Erfassen der statischen Felder und Methoden.

1. Definition: class keyword

Das spezielle keyword class definiert eine Klasse in JavaScript:

class User { // The body of class}

Der obige Code definiert eine class User. Die geschweiften Klammern { } begrenzen den Klassentext. Beachten Sie, dass diese Syntax Klassendeklaration genannt wird.,

Sie sind nicht verpflichtet, den Klassennamen anzugeben. Mithilfe eines Klassenausdrucks können Sie die Klasse einer Variablen zuweisen:

const UserClass = class { // The body of class};

Sie können eine Klasse ganz einfach als Teil eines ES2015-Moduls exportieren. Hier ist die Syntax für einen Standardexport:

export default class User { // The body of class}

Und einen benannten Export:

export class User { // The body of class}

Die Klasse wird nützlich, wenn Sie eine Instanz der Klasse erstellen. Eine Instanz ist ein Objekt, das Daten und Verhalten enthält, die von der Klasse beschrieben werden.,

Der new Operator instanziiert die Klasse in JavaScript: .

Sie können beispielsweise die – Klasse mithilfe des Operators new instanziieren:

const myUser = new User();

new User() erstellt eine Instanz der klasse.

2. Initialisierung: constructor ()

constructor(param1, param2, ...) ist eine spezielle Methode im Hauptteil einer Klasse, die die Instanz initialisiert., Dies ist der Ort, an dem Sie die Anfangswerte für die Felder festlegen oder eine Objekteinrichtung durchführen.

Im folgenden Beispiel setzt der Konstruktor den Anfangswert des Feldes name:

class User { constructor(name) { this.name = name; }}

Der Konstruktor hat einen Parameter name, der verwendet wird, um den Anfangswert des Feldes this.name.

Innerhalb des Konstruktors this Der Wert entspricht der neu erstellten Instanz.,

Die Argumente, die zum Instanziieren der Klasse verwendet werden, werden zu den Parametern des Konstruktors:

class User { constructor(name) { name; // => 'Jon Snow' this.name = name; }}const user = new User('Jon Snow');

name Der Parameter im Konstruktor hat den Wert 'Jon Snow'.

Wenn Sie keinen Konstruktor für die Klasse definieren, wird ein Standardkonstruktor erstellt. Der Standardkonstruktor ist eine leere Funktion, die die Instanz nicht ändert.

Gleichzeitig kann eine JavaScript-Klasse bis zu einem Konstruktor haben.

3. Felder

Klassenfelder sind Variablen, die Informationen enthalten., Felder können an 2 Entitäten angehängt werden:

  1. Felder in der Klasseninstanz
  2. Felder in der Klasse selbst (auch bekannt als statisch)

Die Felder haben auch 2 Barrierefreiheitsstufen:

  1. Public: Das Feld ist überall zugänglich
  2. Private: Das Feld ist nur innerhalb des Hauptteils der Klasse zugänglich

3.1 Felder für öffentliche Instanzen

Schauen wir uns den vorherigen Code snippet:

class User { constructor(name) { this.name = name; }}

Der Ausdruck this.name = name erstellt ein Instanzfeld name und weist ihm einen Anfangswert zu.,

Später können Sie name über einen Eigenschaftenzugriff auf das Feld zugreifen:

const user = new User('Jon Snow');user.name; // => 'Jon Snow'

name ist ein öffentliches Feld, da Sie außerhalb des Klassentextes darauf zugreifen können.

Wenn die Felder wie im vorherigen Szenario implizit im Konstruktor erstellt werden, kann es schwierig sein, die Feldliste zu erfassen. Sie müssen sie aus dem Code des Konstruktors entschlüsseln.

Ein besserer Ansatz besteht darin, die Klassenfelder explizit zu deklarieren., Egal was Konstruktor tut, die Instanz hat immer den gleichen Satz von Feldern.

Mit dem Klassenfeldvorschlag können Sie die Felder im Hauptteil der Klasse definieren. Außerdem können Sie sofort den Anfangswert angeben:

class SomeClass { field1; field2 = 'Initial value'; // ...}

Lassen Sie uns die Klasse ändern und ein öffentliches Feld deklarieren name:

class User { name; constructor(name) { this.name = name; }}const user = new User('Jon Snow');user.name; // => 'Jon Snow'

name;im Hauptteil der Klasse wird ein öffentliches Feld deklariertname.,

Die so deklarierten öffentlichen Felder sind ausdrucksstark: Ein kurzer Blick auf die Felddeklarationen reicht aus, um die Datenstruktur der Klasse zu verstehen.

Darüber hinaus kann das Klassenfeld sofort bei der Deklaration initialisiert werden.

class User { name = 'Unknown'; constructor() { // No initialization }}const user = new User();user.name; // => 'Unknown'

name = 'Unknown' im Klassentext deklariert ein Feld name und initialisiert es mit dem Wert 'Unknown'.

Der Zugriff oder die Aktualisierung der öffentlichen Felder ist nicht eingeschränkt., Sie können öffentliche Felder innerhalb des Konstruktors, der Methoden und außerhalb der Klasse lesen und Werte zuweisen.

3.2 Private Instanzfelder

Die Kapselung ist ein wichtiges Konzept, mit dem Sie die internen Details einer Klasse ausblenden können. Jemand, der eine gekapselte Klasse verwendet, hängt nur von der öffentlichen Schnittstelle ab, die die Klasse bereitstellt, und bezieht sich nicht auf die Implementierungsdetails der Klasse.

Klassen, die unter Berücksichtigung der Kapselung organisiert sind, können leichter aktualisiert werden, wenn sich die Implementierungsdetails ändern.,

Eine gute Möglichkeit, interne Daten eines Objekts auszublenden, ist die Verwendung der privaten Felder. Dies sind die Felder, die nur innerhalb der Klasse gelesen und geändert werden können, zu der sie gehören. Die Außenwelt der Klasse kann private Felder nicht direkt ändern.

Auf die privaten Felder kann nur im Hauptteil der Klasse zugegriffen werden.

Präfix den Feldnamen mit dem speziellen Symbol # um es privat, zB #myField., Das Präfix # muss bei jeder Arbeit mit dem Feld beibehalten werden: deklarieren, lesen oder ändern.

Stellen wir sicher, dass das Feld #name bei der Instanzinitialisierung einmal gesetzt werden kann:

#name ist ein privates Feld. Sie können auf #name im Hauptteil der zugreifen und diese ändern. Die Methode getName() (mehr über Methoden im nächsten Abschnitt) kann auf das private Feld #namezugreifen.,

Wenn Sie jedoch versuchen, auf das private Feld zuzugreifen #name außerhalb von Klassentext wird ein Syntaxfehler ausgelöst: SyntaxError: Private field '#name' must be declared in an enclosing class.

3.3 Öffentliche statische Felder

Sie können auch Felder für die Klasse selbst definieren: die statischen Felder. Diese sind hilfreich, um Klassenkonstanten zu definieren oder klassenspezifische Informationen zu speichern.

Um statische Felder in einer JavaScript-Klasse zu erstellen, verwenden Sie das spezielle Schlüsselwort static gefolgt vom Feldnamen: static myStaticField.,

Fügen wir ein neues Feld type hinzu, das den Benutzertyp angibt: admin oder regular. Die statischen Felder TYPE_ADMIN und TYPE_REGULAR sind praktische Konstanten zur Unterscheidung der Benutzertypen:

static TYPE_ADMIN und static TYPE_REGULAR definieren statische Variablen innerhalb der Klasse. Um auf die statischen Felder zuzugreifen, müssen Sie die Klasse gefolgt vom Feldnamen verwenden: User.TYPE_ADMIN und User.TYPE_REGULAR.

3.,4 Private statische Felder

Manchmal sind sogar die statischen Felder ein Implementierungsdetail, das Sie ausblenden möchten. In dieser Hinsicht können Sie statische Felder privat machen.

Um das statische Feld privat zu machen, setzen Sie dem Feldnamen # Sondersymbol voran: static #myPrivateStaticField.

Angenommen, Sie möchten die Anzahl der Instanzen der Klasse begrenzen., Um die Details zu den Instanzlimits auszublenden, können Sie die privaten statischen Felder erstellen:

Das statische Feld User.#MAX_INSTANCES legt die maximale Anzahl zulässiger Instanzen fest, während das statische Feld User.#instances die tatsächliche Anzahl der Instanzen zählt.

Auf diese privaten statischen Felder kann nur innerhalb der – Klasse zugegriffen werden. Nichts von der Außenwelt kann den Grenzmechanismus stören: Das ist der Vorteil der Kapselung.

4. Methoden

Die Felder enthalten Daten., Die Möglichkeit, Daten zu ändern, wird jedoch von speziellen Funktionen ausgeführt, die Teil der Klasse sind: den Methoden.

Die JavaScript-Klassen unterstützen sowohl Instanzmethoden als auch statische Methoden.

4.1 Instanzmethoden

Instanzmethoden können auf Instanzdaten zugreifen und diese ändern. Instanzmethoden können andere Instanzmethoden sowie jede statische Methode aufrufen.,

Definieren wir beispielsweise eine Methode getName(), die den Namen in der – Klasse zurückgibt:

In einer Klassenmethode sowie im Konstruktor entspricht der Wert this der Klasseninstanz. Verwenden Sie this, um auf Instanzdaten zuzugreifen: this.field oder rufen Sie sogar andere Methoden auf: this.method().,

Fügen wir eine neue Methode hinzu nameContains(str) die einen Parameter hat und eine andere Methode aufruft:

nameContains(str) { ... } ist eine Methode der Klasse, die einen Parameter akzeptiert str. Darüber hinaus führt es eine andere Methode der Instanz this.getName() aus, um den Namen des Benutzers abzurufen.

Eine Methode kann auch privat sein. Um die Methode privat zu machen, Präfix seinen Namen mit #.

Machen wir getName() Methode privat:

#getName() ist eine private Methode., Innerhalb der Methode nameContains(str) rufen Sie eine private Methode wie folgt auf: this.#getName().

Da#getName()

nicht außerhalb des – Klassentextes aufgerufen werden.

4.2 Getter und Setter

Der Getter und Setter imitieren reguläre Felder, haben jedoch mehr Kontrolle darüber, wie auf das Feld zugegriffen und geändert wird.

Der Getter wird ausgeführt, wenn versucht wird, den Feldwert abzurufen, während Setter versucht, einen Wert festzulegen.,

Um sicherzustellen, dass die name Eigenschaft der nicht leer sein kann, wickeln wir das private Feld #nameValue in einen Getter und Setter ein:

get name() {...} getter wird ausgeführt, wenn Sie auf den Wert des Feldes zugreifen: .

4.3 Statische Methoden

Die statischen Methoden sind Funktionen, die direkt an die Klasse angehängt sind. Sie enthalten Logik, die sich auf die Klasse und nicht auf die Instanz der Klasse bezieht.,

Verwenden Sie zum Erstellen einer statischen Methode das spezielle Schlüsselwort static gefolgt von einer regulären Methodensyntax: static myStaticMethod() { ... }.

Bei der Arbeit mit statischen Methoden sind zwei einfache Regeln zu beachten:

  1. Eine statische Methode kann auf statische Felder zugreifen
  2. Eine statische Methode kann nicht auf Instanzfelder zugreifen.

Erstellen wir beispielsweise eine statische Methode, die erkennt, ob ein Benutzer mit einem bestimmten Namen bereits verwendet wurde.,

isNameTaken() ist eine statische Methode, die das statische private Feld User.#takenNames verwendet, um nach getroffenen Namen zu suchen.

5. Vererbung: erweitert

Die Klassen in JavaScript unterstützen die einzelne Vererbung mit dem Schlüsselwort extends.

Im Ausdruck class Child extends Parent { } erbt die Child – Klasse von Parent den Konstruktor, die Felder und die Methoden.

Erstellen wir beispielsweise eine neue untergeordnete Klasse ContentWriter, die die übergeordnete Klasse erweitert .,

ContentWriter erbt vom den Konstruktor, die Methode getName() und das Feld name. Auch dieContentWriter Klasse deklariert ein neues Feldposts.

Beachten Sie, dass private Mitglieder einer übergeordneten Klasse nicht von der untergeordneten Klasse vererbt werden.

5.1 Übergeordneter Konstruktor: super() in constructor ()

Wenn Sie den übergeordneten Konstruktor in einer untergeordneten Klasse aufrufen möchten, müssen Sie die spezielle Funktion super() verwenden, die im untergeordneten Konstruktor verfügbar ist.,

Lassen Sie uns beispielsweise ContentWriter Konstruktor den übergeordneten Konstruktor von aufrufen und das posts-Feld initialisieren:

super(name) innerhalb der untergeordneten Klasse ContentWriter führt den Konstruktor der übergeordneten Klasse aus .

Beachten Sie, dass Sie innerhalb des untergeordneten Konstruktors super() ausführen müssen, bevor Sie das Schlüsselwort this. Der Aufruf von super() stellt sicher, dass der übergeordnete Konstruktor die Instanz initialisiert.,

class Child extends Parent { constructor(value1, value2) { // Does not work! this.prop2 = value2; super(value1); }}

5.2 Übergeordnete Instanz: super in Methoden

Wenn Sie auf die übergeordnete Methode innerhalb einer untergeordneten Methode zugreifen möchten, können Sie die spezielle Verknüpfung super.

getName() der untergeordneten Klasse ContentWriter greift direkt aus der übergeordneten Klasse auf die Methode zu .

Diese Funktion wird als Methode überschreiben.

Beachten Sie, dass Sie super auch mit statischen Methoden verwenden können, um auf die statischen Methoden des Elternteils zuzugreifen.

6., Object type checking: instanceof

object instanceof Class is the operator that determines if object is an instance of Class.

Let’s see instanceof operator in action:

user is an instance of User class, user instanceof User evaluates to true.

The empty object {} is not an instance of User, correspondingly obj instanceof User is false.,

instanceof ist polymorph: Der Operator erkennt ein Kind als Instanz der übergeordneten Klasse.

writer ist eine Instanz der untergeordneten Klasse ContentWriter. Der Operator writer instanceof ContentWriter wertet trueaus.

Gleichzeitig ist ContentWriter eine untergeordnete Klasse von User. Alsowriter instanceof User wertet auchtrue aus.

Was ist, wenn Sie die genaue Klasse der Instanz bestimmen möchten?, Sie können die Eigenschaft constructor verwenden und direkt mit der Klasse vergleichen:

writer.constructor === ContentWriter; // => truewriter.constructor === User; // => false

7. Klassen und Prototypen

Ich muss sagen, dass die Klassensyntax in JavaScript großartige Arbeit leistet, um von der prototypischen Vererbung zu abstrahieren. Um die class Syntax zu beschreiben, habe ich nicht einmal den Begriff Prototyp verwendet.

Aber die Klassen sind auf der prototypischen Vererbung aufgebaut. Jede Klasse ist eine Funktion und erstellt eine Instanz, wenn sie als Konstruktor aufgerufen wird.

Die folgenden zwei Codeausschnitte sind äquivalent.,

Die Klassenversion:

Die Version mit prototype:

Die Klassensyntax ist viel einfacher zu arbeiten, wenn Sie mit dem klassischen Vererbungsmechanismus von Java oder Swift vertraut sind Sprachen.

Selbst wenn Sie die Klassensyntax in JavaScript verwenden, empfehle ich Ihnen, die prototypische Vererbung gut zu verstehen.

8. Verfügbarkeit von Klassenfunktionen

Die in diesem Beitrag vorgestellten Klassenfunktionen sind auf ES2015 und Vorschläge in Stufe 3 verteilt.,

Am Ende von 2019 werden die Klassenmerkmale aufgeteilt zwischen:

  • Öffentliche und private Instanzfelder sind Teil von Klassenfeldern Vorschlag
  • Private Instanzmethoden und Accessoren sind Teil von Class private methods Vorschlag
  • Öffentliche und private statische Felder und private statische Methoden sind Teil von Class static features Vorschlag
  • Der Rest ist Teil des ES2015-Standards.

9. Schlussfolgerung

JavaScript-Klassen initialisieren Instanzen mit Konstruktoren, definieren Felder und Methoden., Sie können Felder und Methoden sogar an die Klasse selbst anhängen, indem Sie das Schlüsselwort static.

Vererbung wird mit extends Schlüsselwort erreicht: Sie können ganz einfach eine untergeordnete Klasse von einem Elternteil erstellen. super wird verwendet, um von einer untergeordneten Klasse aus auf die übergeordnete Klasse zuzugreifen.

Um die Kapselung zu nutzen, machen Sie die Felder und Methoden privat, um die internen Details Ihrer Klassen auszublenden. Die privaten Felder und Methodennamen müssen mit #beginnen.,

Die Klassen in JavaScript werden immer bequemer zu bedienen.

Was halten Sie von der Verwendung von # zum Präfix privater Eigenschaften?