new.target
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2016.
Die new.target Metaeigenschaft ermöglicht es Ihnen, zu erkennen, ob eine Funktion oder ein Konstruktor unter Verwendung des new Operators aufgerufen wurde. In Konstruktoren und Funktionen, die mit dem new Operator aufgerufen werden, gibt new.target eine Referenz auf den Konstruktor oder die Funktion zurück, auf die new angewendet wurde. Bei normalen Funktionsaufrufen ist new.target undefined.
Probieren Sie es aus
Syntax
new.target
Wert
new.target ist garantiert entweder eine konstruierbare Funktionswert oder undefined.
- In Klassenkonstruktoren bezieht es sich auf die Klasse, auf die
newaufgerufen wurde, die möglicherweise eine Unterklasse des aktuellen Konstruktors ist, da Unterklassen transitiv den Konstruktor der Oberklasse übersuper()aufrufen. - In gewöhnlichen Funktionen, wenn die Funktion direkt mit
newkonstruiert wird, bezieht sichnew.targetauf die Funktion selbst. Wenn die Funktion ohnenewaufgerufen wird, istnew.targetundefined. Funktionen können als Basisklasse fürextendsverwendet werden, in welchem Fallnew.targetauf die Unterklasse verweisen kann. - Wenn ein Konstruktor (Klasse oder Funktion) über
Reflect.construct()aufgerufen wird, bezieht sichnew.targetauf den Wert, der alsnewTargetübergeben wird (der standardmäßigtargetist). - In Pfeilfunktionen wird
new.targetvom umgebenden Gültigkeitsbereich vererbt. Wenn die Pfeilfunktion nicht innerhalb einer anderen Klasse oder Funktion definiert ist, die einenew.targetBindung hat, wird ein Syntaxfehler ausgelöst. - In statischen Initialisierungsblöcken ist
new.targetundefined.
Beschreibung
Die new.target Syntax besteht aus dem Schlüsselwort new, einem Punkt und dem Identifier target. Da new ein reserviertes Wort ist und kein Identifier, handelt es sich hierbei nicht um einen Eigenschafts-Accessor, sondern um eine spezielle Ausdruckssyntax.
Die new.target Metaeigenschaft ist in allen Funktions-/Klassenkörpern verfügbar; die Verwendung von new.target außerhalb von Funktionen oder Klassen führt zu einem Syntaxfehler.
Beispiele
new.target in Funktionsaufrufen
Bei normalen Funktionsaufrufen (im Gegensatz zu Konstruktorfunktionsaufrufen) ist new.target undefined. Dies ermöglicht es Ihnen zu erkennen, ob eine Funktion als Konstruktor mit new aufgerufen wurde.
function Foo() {
if (!new.target) {
throw new Error("Foo() must be called with new");
}
console.log("Foo instantiated with new");
}
new Foo(); // Logs "Foo instantiated with new"
Foo(); // Throws "Foo() must be called with new"
new.target in Konstruktoren
In Klassenkonstruktoren bezieht sich new.target auf den Konstruktor, der direkt durch new aufgerufen wurde. Dies gilt auch, wenn der Konstruktor sich in einer übergeordneten Klasse befindet und von einem untergeordneten Konstruktor delegiert wurde. new.target zeigt auf die Klasse, auf die new angewendet wurde. Zum Beispiel, wenn b mit new B() initialisiert wurde, wurde der Name von B ausgegeben; und ähnlich, im Fall von a, wurde der Name der Klasse A ausgegeben.
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {
constructor() {
super();
}
}
const a = new A(); // Logs "A"
const b = new B(); // Logs "B"
new.target mit Reflect.construct()
Vor Reflect.construct() oder Klassen war es üblich, Vererbung zu implementieren, indem der Wert von this übergeben und der Basiskonstruktor diesen mutiert.
function Base() {
this.name = "Base";
}
function Extended() {
// Only way to make the Base() constructor work on the existing
// `this` value instead of a new object that `new` creates.
Base.call(this);
this.otherProperty = "Extended";
}
Object.setPrototypeOf(Extended.prototype, Base.prototype);
Object.setPrototypeOf(Extended, Base);
console.log(new Extended()); // Extended { name: 'Base', otherProperty: 'Extended' }
Allerdings rufen call() und apply() die Funktion tatsächlich auf statt sie zu konstruieren, sodass new.target den Wert undefined hat. Das bedeutet, dass wenn Base() prüft, ob es mit new konstruiert wurde, ein Fehler ausgelöst wird oder es sich auf andere unerwartete Weisen verhält. Zum Beispiel können Sie Map nicht auf diese Weise erweitern, da der Map() Konstruktor nicht ohne new aufgerufen werden kann.
Alle eingebauten Konstruktoren konstruieren direkt die gesamte Prototypkette der neuen Instanz, indem sie new.target.prototype lesen. Um also sicherzustellen, dass (1) Base mit new konstruiert wird und (2) new.target auf die Unterklasse statt auf Base selbst zeigt, müssen wir Reflect.construct() verwenden.
function BetterMap(entries) {
// Call the base class constructor, but setting `new.target` to the subclass,
// so that the instance created has the correct prototype chain.
return Reflect.construct(Map, [entries], BetterMap);
}
BetterMap.prototype.upsert = function (key, actions) {
if (this.has(key)) {
this.set(key, actions.update(this.get(key)));
} else {
this.set(key, actions.insert());
}
};
Object.setPrototypeOf(BetterMap.prototype, Map.prototype);
Object.setPrototypeOf(BetterMap, Map);
const map = new BetterMap([["a", 1]]);
map.upsert("a", {
update: (value) => value + 1,
insert: () => 1,
});
console.log(map.get("a")); // 2
Hinweis: Tatsächlich ist es aufgrund des fehlenden Reflect.construct() nicht möglich, eingebaute Objekte (wie beim Error Unterklassen) korrekt zu subklassifizieren, wenn auf prä-ES6-Code transpiliert wird.
Wenn Sie jedoch ES6-Code schreiben, bevorzugen Sie es, Klassen und extends zu verwenden, da dies lesbarer und weniger fehleranfällig ist.
class BetterMap extends Map {
// The constructor is omitted because it's just the default one
upsert(key, actions) {
if (this.has(key)) {
this.set(key, actions.update(this.get(key)));
} else {
this.set(key, actions.insert());
}
}
}
const map = new BetterMap([["a", 1]]);
map.upsert("a", {
update: (value) => value + 1,
insert: () => 1,
});
console.log(map.get("a")); // 2
Spezifikationen
| Specification |
|---|
| ECMAScript Language Specification # sec-built-in-function-objects |
Browser-Kompatibilität
BCD tables only load in the browser