W3docs

JavaScript new-Operator

Lerne, wie Konstruktorfunktionen und der new-Operator in JavaScript Objekte erzeugen: was new Schritt für Schritt tut, die Rückgabewert-Regel, new.target und Namenskonventionen.

Einführung in Konstruktoren und den new-Operator

In JavaScript sind Konstruktoren Funktionen, die dazu dienen, neu erstellte Objekte zu initialisieren. Sie spielen eine zentrale Rolle in der objektorientierten Programmierung, da Entwickler damit Eigenschaften und Verhaltensweisen definieren können, die Objekte einer bestimmten Klasse besitzen sollen. Der new-Operator wird verwendet, um eine Instanz eines Objekts auf Basis einer Konstruktorfunktion zu erzeugen – er richtet eine neue Objektumgebung basierend auf dem angegebenen Prototyp ein und führt den Konstruktor aus, um das neue Objekt zu initialisieren.

Wie Konstruktoren funktionieren

Eine Konstruktorfunktion in JavaScript sieht aus wie jede andere Funktion, wird aber per Konvention mit einem Großbuchstaben benannt, um sie von regulären Funktionen zu unterscheiden. Wenn der new-Operator eine Konstruktorfunktion aufruft, laufen hinter den Kulissen vier Dinge ab, die in etwa diesem Pseudocode entsprechen:

function User(name) {
  // this = {};  (1) an empty object is created and assigned to this
  // this.__proto__ = User.prototype;  (2) prototype is linked

  this.name = name;  // (3) the constructor body runs, adding properties to this

  // return this;  (4) this is returned automatically
}
  1. Ein neues leeres object wird erstellt und this zugewiesen.
  2. Der Prototyp wird verknüpft: Das interne [[Prototype]] des neuen Objekts wird auf die prototype-Eigenschaft des Konstruktors gesetzt, sodass es dort definierte Eigenschaften und Methoden erbt.
  3. Der Konstruktorrumpf wird ausgeführt: Die Funktion läuft mit den übergebenen Argumenten, und this verweist auf das brandneue object – Zuweisungen wie this.name = name hängen so Eigenschaften daran.
  4. Das object wird zurückgegeben: this wird automatisch zurückgegeben, es sei denn, der Konstruktor gibt explizit ein anderes object zurück (siehe Die Rückgabewert-Regel weiter unten).
Info

Modernes JavaScript verwendet die class-Syntax, um Konstruktoren und Methoden intuitiver zu definieren. Dies bietet einen klareren, klassenbasierten Ansatz, der anderen Programmiersprachen ähnelt.

Beispiel: Einfache Konstruktorfunktion

javascript— editable

Erklärung: In diesem Beispiel ist User eine Konstruktorfunktion, die name, age und eine greet-Methode auf neu erstellten Objekten initialisiert. Die Anweisung new User('John', 30) erzeugt eine neue Instanz von User mit dem Namen „John" und dem Alter 30. Innerhalb von greet verweist this auf das object, auf dem die Methode aufgerufen wurde.

Die Rückgabewert-Regel

Konstruktoren verwenden normalerweise kein return – das neue object (this) wird automatisch zurückgegeben. return hat jedoch ein spezielles, leicht zu übersehendes Verhalten innerhalb eines Konstruktors:

  • Folgt auf return ein object, wird dieses object anstelle von this zurückgegeben.
  • Folgt auf return ein Primitiver Wert (string, number, boolean, undefined usw.), wird er ignoriert und this wie gewohnt zurückgegeben.
javascript— editable

Erklärung: WithObject gibt ein einfaches object zurück, weshalb dieses die Instanz vollständig ersetzt. WithPrimitive gibt einen string zurück, der ignoriert wird – es wird das ursprüngliche this (mit name: 'Alice') zurückgegeben. Man verlässt sich selten darauf, aber es erklärt überraschende Ergebnisse, wenn ein Konstruktor versehentlich einen Wert zurückgibt.

new erkennen mit new.target

Innerhalb jeder Funktion ist new.target undefined, wenn die Funktion normal aufgerufen wird, und gleich der Funktion selbst, wenn sie mit new aufgerufen wird. Damit kann ein Konstruktor erkennen, wie er aufgerufen wurde – nützlich, um das new-Schlüsselwort zu erzwingen oder stillschweigend zu erlauben.

javascript— editable

Erklärung: Da Modal new.target prüft, wird Modal('Without new') ohne new transparent an new Modal(...) weitergeleitet, sodass b trotzdem eine echte Modal-Instanz ist. (Hinweis: Viele Teams ziehen es vor, dies nicht zu tun und einen fehlenden new-Aufruf laut scheitern zu lassen.)

Wann sollte ich einen Konstruktor verwenden?

Verwende eine Konstruktorfunktion (oder eine class), wenn du viele Objekte gleicher Struktur erstellen musst – mehrere Benutzer, Autos, DOM-Widgets usw. Der Konstruktor zentralisiert die Einrichtungslogik, sodass jede Instanz auf die gleiche Weise gebaut wird und Methoden über den Prototyp teilt.

Benötigst du nur ein einzelnes object, ist ein einfaches object-Literal { ... } einfacher. Für ein einmaliges object, das dennoch von einem Konstruktorrumpf profitiert, kann man sogar einen anonymen Konstruktor verwenden:

javascript— editable

Erklärung: Die anonyme function wird einmalig als Konstruktor ausgeführt und nirgendwo gespeichert, sodass sie nicht wiederverwendet werden kann – sie dient lediglich dazu, eine komplexe einmalige Einrichtung zu kapseln.

Konstruktorfunktionen vs. Klassen

Moderner Code bevorzugt in der Regel die class-Syntax, die im Wesentlichen syntaktischer Zucker über Konstruktorfunktionen und Prototypen ist. Die beiden folgenden Schnipsel sind gleichwertig:

javascript— editable

Klassen bieten echte Vorteile gegenüber Konstruktorfunktionen: Methoden sind standardmäßig nicht aufzählbar, der Rumpf läuft im Strict Mode, das Aufrufen einer Klasse ohne new wirft einen Fehler, und extends/super machen Vererbung deutlich sauberer. Konstruktorfunktionen sind dennoch wichtig zu verstehen, da Klassen auf demselben Prototyp-Mechanismus aufbauen und man ihnen in älterem Code noch begegnet.

Konstruktoren für komplexe Objekte verwenden

Konstruktoren können eingesetzt werden, um komplexere Beziehungen zwischen Objekten aufzubauen, einschließlich Methoden, die mit anderen Eigenschaften der Objekte interagieren.

Beispiel: Konstruktor mit Methoden

javascript— editable

Erklärung: Der Car-Konstruktor stattet jedes Auto-object mit spezifischen Eigenschaften und einer Methode aus, die Informationen über das Auto anzeigt.

Beispiel: Prototyp-Methoden

javascript— editable

Erklärung: Indem introduce dem Employee-Prototyp hinzugefügt wird, teilen alle Instanzen dieselbe Methode, was speichereffizienter ist als die Definition direkt im Konstruktor.

Warnung

Es wird empfohlen, ES6-Klassen zur Definition von Objekten und Konstruktoren zu verwenden, um saubereren und besser lesbaren Code zu schreiben.

Best Practices mit Konstruktoren

Beim Arbeiten mit Konstruktoren in JavaScript können bestimmte Best Practices die Lesbarkeit, Effizienz und Skalierbarkeit des Codes erheblich verbessern. Nachfolgend werden die Praktiken mit ausführlichen Beispielen und Erklärungen erläutert:

1. Namenskonvention

Best Practice: Beginne Konstruktornamen immer mit einem Großbuchstaben, um sie von regulären Funktionen zu unterscheiden. Dies ist eine gängige Konvention in JavaScript und vielen anderen Programmiersprachen, die Entwicklern hilft, Konstruktorfunktionen schnell zu erkennen.

Beispiel:

javascript— editable

Erklärung: Die Konstruktorfunktion Laptop beginnt mit einem Großbuchstaben, was darauf hinweist, dass sie mit dem new-Operator zur Erstellung neuer Objekte verwendet werden soll.

2. Logik trennen

Best Practice: Für Methoden, die keinen Zugriff auf individuelle Instanzdaten benötigen, definiere sie lieber auf dem Prototyp des Konstruktors als innerhalb des Konstruktors selbst. Dieser Ansatz spart Speicher, da alle Instanzen dieselbe Methode teilen, anstatt dass jede Instanz eine neue Funktion im Speicher erzeugt.

Beispiel:

javascript— editable

Erklärung: Die describe-Methode wird dem Book-Prototyp hinzugefügt, was bedeutet, dass alle Instanzen von Book dieselbe describe-Methode teilen. Dies ist effizienter, als describe innerhalb des Konstruktors zu definieren, was für jede Buchinstanz eine neue Funktion ergeben würde.

3. Rückgabewerte

Best Practice: Vermeide es, Werte aus Konstruktoren zurückzugeben. JavaScript-Konstruktoren geben automatisch die neue Objektinstanz zurück, sofern nicht explizit ein anderes object zurückgegeben wird. Das Zurückgeben von Nicht-object-Werten (wie ein string oder eine Zahl) hat keine Wirkung – die neue Instanz wird trotzdem zurückgegeben.

Beispiel:

javascript— editable

Erklärung: Obwohl versucht wird, einen string aus dem Player-Konstruktor zurückzugeben, ignoriert JavaScript diesen Rückgabewert, weil er kein object ist. Die neue Player-Instanz wird wie erwartet zurückgegeben.

Fazit

Das Verstehen und der Einsatz von Konstruktoren und dem new-Operator in JavaScript ist für effektive objektorientierte Programmierung unerlässlich. Indem man die hier beschriebenen Konventionen und Best Practices befolgt, können Entwickler organisierten, effizienten und skalierbaren Code erstellen. Konstruktoren bieten einen leistungsstarken Mechanismus zur Initialisierung neuer Objekte und zur strukturierten und intuitiven Definition ihres Verhaltens.

Um tiefer einzutauchen, erforsche, wie Konstruktoren Verhalten über prototypische Vererbung teilen, wie die class-Syntax auf diesen Ideen aufbaut und wie eine Funktion auch ein object mit eigenen Eigenschaften ist.

Übungen

Übung
Was passiert, wenn eine Funktion in JavaScript mit 'new' ausgeführt wird?
Was passiert, wenn eine Funktion in JavaScript mit 'new' ausgeführt wird?
Was this page helpful?