Signatur
Beschreibung
Wenn eine Funktion mit dem Schlüsselwort new aufgerufen wird, wird die Funktion als Konstruktor verwendet. new führt Folgendes aus:
- Erzeugt ein leeres, einfaches JavaScript-Objekt. Nennen wir es der Einfachheit halber
newInstance. - Setzt das [[Prototype]] von
newInstanceauf dieprototype-Eigenschaft der Konstruktorfunktion, sofernprototypeeinObjectist. Andernfalls bleibtnewInstanceein einfaches Objekt mitObject.prototypeals [[Prototype]]. - Führt die Konstruktorfunktion mit den angegebenen Argumenten aus, wobei
newInstancealsthis-Kontext gebunden wird (d. h. alle Verweise aufthisin der Konstruktorfunktion beziehen sich nun aufnewInstance). - 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 stattdessennewInstancezurü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:
- Definiere den Objekttyp, indem du eine Funktion schreibst, die seinen Namen und seine Eigenschaften angibt.
- 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()undFunction()verhalten sich gleich, ob als Funktion oder als Konstruktor aufgerufen.Boolean(),Number()undString()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 zunew Date().toString().
Seit ES6 ist die Sprache strenger darin, was Konstruktoren und was Funktionen sind. Zum Beispiel:
Symbol()undBigInt()können nur ohnenewaufgerufen werden. Der Versuch, sie zu konstruieren, wirft einenTypeError.ProxyundMapkönnen nur mitnewkonstruiert werden. Der Versuch, sie aufzurufen, wirft einenTypeError.
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
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
newwerfen einenTypeError:Class constructor X cannot be invoked without 'new'. - Arrow-Funktionen können nicht als Konstruktoren mit
newverwendet werden — sie besitzen kein eigenesthisund keinenprototype. Ein Versuch führt zu einemTypeError. - 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.