Start · Sprachen · JavaScript · Referenz · new

new

Operator

Der <code>new</code>-Operator erzeugt eine Instanz eines benutzerdefinierten Objekttyps oder eines eingebauten Objekttyps mit Konstruktorfunktion.

seit JavaScript ES1 Kategorie: syntax

Signatur

new constructor new constructor() new constructor(arg1) new constructor(arg1, arg2) new constructor(arg1, arg2, /* …, */ argN)

Beschreibung

Wenn eine Funktion mit dem Schlüsselwort new aufgerufen wird, wird die Funktion als Konstruktor verwendet. new führt Folgendes aus:

  1. Erzeugt ein leeres, einfaches JavaScript-Objekt. Nennen wir es der Einfachheit halber newInstance.
  2. Setzt das [[Prototype]] von newInstance auf die prototype-Eigenschaft der Konstruktorfunktion, sofern prototype ein Object ist. Andernfalls bleibt newInstance ein einfaches Objekt mit Object.prototype als [[Prototype]].
  3. Führt die Konstruktorfunktion mit den angegebenen Argumenten aus, wobei newInstance als this-Kontext gebunden wird (d. h. alle Verweise auf this in der Konstruktorfunktion beziehen sich nun auf newInstance).
  4. Wenn die Konstruktorfunktion einen nicht-primitiven Wert zurückgibt, wird dieser Rückgabewert zum Ergebnis des gesamten new-Ausdrucks. Andernfalls, wenn die Konstruktorfunktion nichts zurückgibt oder einen primitiven Wert zurückgibt, wird stattdessen newInstance zurückgegeben. (Normalerweise geben Konstruktoren keinen Wert zurück, sie können dies aber tun, um den normalen Objekterzeugungsprozess zu überschreiben.)

Eigenschaften/Objekte, die zur prototype-Eigenschaft der Konstruktorfunktion hinzugefügt werden, sind daher für alle aus der Konstruktorfunktion erzeugten Instanzen zugänglich.

Classes können nur mit dem new-Operator instanziiert werden — der Versuch, eine Class ohne new aufzurufen, wirft einen TypeError.

Das Erstellen eines Objekts mit einer benutzerdefinierten Konstruktorfunktion erfordert zwei Schritte:

  1. Definiere den Objekttyp, indem du eine Funktion schreibst, die seinen Namen und seine Eigenschaften angibt.
  2. Erzeuge eine Instanz des Objekts mit new.

Ein Objekt kann eine Eigenschaft haben, die selbst ein weiteres Objekt ist. Siehe die Beispiele unten.

Du kannst einer bereits definierten Objektinstanz jederzeit eine Eigenschaft hinzufügen. Beispielsweise fügt die Anweisung car1.color = "black" dem Objekt car1 eine Eigenschaft color hinzu und weist ihr den Wert "black" zu.

Dies wirkt sich jedoch nicht auf andere Objekte aus. Um die neue Eigenschaft allen Objekten desselben Typs hinzuzufügen, musst du die Eigenschaft der prototype-Eigenschaft des Konstruktors hinzufügen. Dies definiert eine Eigenschaft, die von allen mit dieser Funktion erzeugten Objekten geteilt wird, statt nur von einer Instanz des Objekttyps.

Obwohl die Konstruktorfunktion wie jede reguläre Funktion aufgerufen werden kann (d. h. ohne den new-Operator), wird in diesem Fall kein neues Objekt erzeugt und der Wert von this ist ebenfalls ein anderer.

Eine Funktion kann prüfen, ob sie mit new aufgerufen wurde, indem sie new.target abfragt. new.target ist nur dann undefined, wenn die Funktion ohne new aufgerufen wird. Beispielsweise kannst du eine Funktion haben, die sich beim Aufruf anders verhält als beim Konstruieren.

Vor ES6, das classes eingeführt hat, sind die meisten JavaScript-Built-ins sowohl aufrufbar als auch konstruierbar, wobei viele von ihnen unterschiedliche Verhaltensweisen aufweisen. Um einige zu nennen:

  • Array(), Error() und Function() verhalten sich gleich, ob als Funktion oder als Konstruktor aufgerufen.
  • Boolean(), Number() und String() wandeln ihr Argument beim Aufruf in den jeweiligen primitiven Typ um und geben beim Konstruieren Wrapper-Objekte zurück.
  • Date() gibt beim Aufruf einen String zurück, der das aktuelle Datum repräsentiert, äquivalent zu new Date().toString().

Seit ES6 ist die Sprache strenger darin, was Konstruktoren und was Funktionen sind. Zum Beispiel:

  • Symbol() und BigInt() können nur ohne new aufgerufen werden. Der Versuch, sie zu konstruieren, wirft einen TypeError.
  • Proxy und Map können nur mit new konstruiert werden. Der Versuch, sie aufzurufen, wirft einen TypeError.

Parameter

Name Typ Default Beschreibung
$constructor Pflicht Function | Class Eine Class oder Funktion, die den Typ der Objektinstanz angibt. Der Ausdruck kann alles mit ausreichender Präzedenz sein, einschließlich eines Identifiers, eines Property Access oder eines weiteren new-Ausdrucks, aber optional chaining ist nicht erlaubt.
$arg1, arg2, …, argN any Eine Liste von Werten, mit denen der constructor aufgerufen wird. new Foo ist äquivalent zu new Foo(), d. h. wenn keine Argumentliste angegeben wird, wird Foo ohne Argumente aufgerufen.

Rückgabewert

Typ
object
Beschreibung
Eine neue Objektinstanz, deren Prototypkette mit Constructor.prototype verknüpft ist. Gibt der Konstruktor explizit ein anderes Objekt zurück, wird dieses zurückgegeben.

Beispiele

Objekttyp und Objektinstanz

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

const myCar = new Car("Eagle", "Talon TSi", 1993);

const kensCar = new Car("Nissan", "300ZX", 1992);

Objekteigenschaft, die selbst ein weiteres Objekt ist

function Person(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}

const rand = new Person("Rand McNally", 33, "M");
const ken = new Person("Ken Jones", 39, "M");

function Car(make, model, year, owner) {
  this.make = make;
  this.model = model;
  this.year = year;
  this.owner = owner;
}

const car1 = new Car("Eagle", "Talon TSi", 1993, rand);
const car2 = new Car("Nissan", "300ZX", 1992, ken);

car2.owner.name;

Prototype-Eigenschaften für alle Instanzen

function Car() {}
const car1 = new Car();
const car2 = new Car();

console.log(car1.color); // undefined

Car.prototype.color = "original color";
console.log(car1.color); // 'original color'

car1.color = "black";
console.log(car1.color); // 'black'

console.log(Object.getPrototypeOf(car1).color); // 'original color'
console.log(Object.getPrototypeOf(car2).color); // 'original color'
console.log(car1.color); // 'black'
console.log(car2.color); // 'original color'

new.target zur Unterscheidung von Aufruf und Konstruktion

function Car(color) {
  if (!new.target) {
    // Als Funktion aufgerufen.
    return `${color} car`;
  }
  // Mit new aufgerufen.
  this.color = color;
}

const a = Car("red"); // a ist "red car"
const b = new Car("red"); // b ist `Car { color: "red" }`

new mit classes verwenden

class Person {
  constructor(name) {
    this.name = name;
  }
  greet() {
    console.log(`Hello, my name is ${this.name}`);
  }
}

const p = new Person("Caroline");
p.greet(); // Hello, my name is Caroline

// Wichtig · Fallstricke

Kein new ohne Konstruktor-Absicht: Wird new mit einer normalen Funktion verwendet, die keinen Rückgabewert oder einen primitiven Rückgabewert hat, gibt new immer das neu erstellte Objekt zurück — der primitive Rückgabewert wird schlicht ignoriert.

  • Klassen ohne new werfen einen TypeError: Class constructor X cannot be invoked without 'new'.
  • Arrow-Funktionen können nicht als Konstruktoren mit new verwendet werden — sie besitzen kein eigenes this und keinen prototype. Ein Versuch führt zu einem TypeError.
  • Wrapper-Konstruktoren (new Boolean(), new Number(), new String()) sind in modernem JavaScript zu vermeiden, da sie Objekte statt primitiver Werte liefern und zu verwirrenden Vergleichsergebnissen führen.
  • Soll eine Funktion dynamisch mit einer variablen Argumentliste aufgerufen werden, bietet sich Reflect.construct(Constructor, args) als moderne Alternative an.