Reflect.construct()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
Die statische Methode Reflect.construct()
ähnelt dem new
Operator, ist aber eine Funktion. Sie entspricht dem Aufruf von new target(...args)
. Zusätzlich ermöglicht sie es, einen anderen Wert als new.target
anzugeben.
Probieren Sie es aus
Syntax
Reflect.construct(target, argumentsList)
Reflect.construct(target, argumentsList, newTarget)
Parameter
target
-
Die Ziel-Funktion, die aufgerufen werden soll.
argumentsList
-
Ein array-artiges Objekt, das die Argumente angibt, mit denen
target
aufgerufen werden soll. newTarget
Optional-
Der Wert des Ausdrucks
new.target
innerhalb vontarget
. Standardmäßigtarget
. Im Allgemeinen (siehe Beispiel) gibttarget
die Logik zur Initialisierung des Objekts an, währendnewTarget.prototype
das Prototyp des konstruierten Objekts angibt.
Rückgabewert
Eine neue Instanz von target
(oder newTarget
, falls vorhanden), die durch target
als Konstruktor mit dem angegebenen argumentsList
initialisiert wurde.
Ausnahmen
TypeError
-
Ausgelöst, wenn
target
odernewTarget
kein Konstruktor ist oder wennargumentsList
kein Objekt ist.
Beschreibung
Reflect.construct()
bietet die reflektive Semantik eines Konstruktoraufrufs. Das bedeutet, Reflect.construct(target, argumentsList, newTarget)
ist semantisch äquivalent zu:
new target(...argumentsList);
Beachten Sie, dass beim Verwenden des new
Operators target
und newTarget
immer derselbe Konstruktor sind — jedoch ermöglicht Reflect.construct()
, einen anderen new.target
Wert zu übergeben. Konzeptuell ist newTarget
die Funktion, bei der new
aufgerufen wurde, und newTarget.prototype
wird zum Prototyp des konstruierten Objekts, während target
der Konstruktor ist, der tatsächlich ausgeführt wird, um das Objekt zu initialisieren. Beispielsweise kann new.target
auch in der Klassenvererbung von dem momentan ausgeführten Konstruktor abweichen.
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {}
new B(); // "B"
Reflect.construct()
ermöglicht es Ihnen, einen Konstruktor mit einer variablen Anzahl von Argumenten aufzurufen. (Dies ist auch mit der Spread-Syntax in einem normalen Konstruktoraufruf möglich.)
const obj = new Foo(...args);
const obj = Reflect.construct(Foo, args);
Reflect.construct()
ruft die [[Construct]]
interne Objektmethode von target
auf.
Beispiele
Verwendung von Reflect.construct()
const d = Reflect.construct(Date, [1776, 6, 4]);
d instanceof Date; // true
d.getFullYear(); // 1776
Ändern von new.target
Wenn newTarget
übergeben wird, ändert es den Wert von new.target
innerhalb des Konstruktors. Das konstruierte Objekt wird eine Instanz von newTarget
und nicht von target
.
function OneClass() {
console.log("OneClass executed");
console.log(`new.target is ${new.target.name}`);
}
function OtherClass() {
console.log("OtherClass executed");
console.log(`new.target is ${new.target.name}`);
}
const obj1 = Reflect.construct(OneClass, []);
// Logs:
// OneClass executed
// new.target is OneClass
console.log(obj1 instanceof OneClass); // true
const obj2 = Reflect.construct(OneClass, [], OtherClass);
// Logs:
// OneClass executed
// new.target is OtherClass
console.log(obj2 instanceof OtherClass); // true
console.log(obj2 instanceof OneClass); // false
Natürlich gibt es keine starke Garantie in Bezug auf die Prototyp-Kette des konstruierten Objekts, da diese von der Implementierung des Konstruktors abhängt. Zum Beispiel, wenn der target
-Konstruktor ein Objekt zurückgibt, dann wird dieses Objekt das konstruierte Objekt sein, unabhängig vom newTarget
-Wert. Wenn target
ein Proxy mit einer construct
-Falle ist, dann kontrolliert die Falle den gesamten Konstruktionsprozess.
function OneClass() {
return { name: "one" };
}
function OtherClass() {
return { name: "other" };
}
const obj1 = Reflect.construct(OneClass, [], OtherClass);
console.log(obj1.name); // 'one'
console.log(obj1 instanceof OneClass); // false
console.log(obj1 instanceof OtherClass); // false
Ein gültiges new.target
sollte eine Konstruktorfunktion mit einer prototype
Eigenschaft sein, aber letzteres wird nicht erzwungen. Wenn der Wert der prototype
-Eigenschaft kein Objekt ist, wird das initialisierte Objekt von Object.prototype
erben.
function OneClass() {
console.log("OneClass executed");
console.log(`new.target is ${new.target.name}`);
}
function OtherClass() {
console.log("OtherClass executed");
console.log(`new.target is ${new.target.name}`);
}
OtherClass.prototype = null;
const obj = Reflect.construct(OneClass, [], OtherClass);
// Logs:
// OneClass executed
// new.target is OtherClass
console.log(Object.getPrototypeOf(obj) === Object.prototype); // true
Reflect.construct() vs. Object.create()
Vor der Einführung von Reflect
konnten Objekte mit einer beliebigen Kombination aus Konstruktoren und Prototypen mit Object.create()
konstruiert werden.
function OneClass() {
this.name = "one";
}
function OtherClass() {
this.name = "other";
}
const args = [];
const obj1 = Reflect.construct(OneClass, args, OtherClass);
const obj2 = Object.create(OtherClass.prototype);
OneClass.apply(obj2, args);
console.log(obj1.name); // 'one'
console.log(obj2.name); // 'one'
console.log(obj1 instanceof OneClass); // false
console.log(obj2 instanceof OneClass); // false
console.log(obj1 instanceof OtherClass); // true
console.log(obj2 instanceof OtherClass); // true
Obwohl das Endergebnis das gleiche ist, gibt es einen wichtigen Unterschied im Prozess. Beim Verwenden von Object.create()
und Function.prototype.apply()
zeigt der new.target
Operator innerhalb der Funktion, die als Konstruktor verwendet wird, auf undefined
, da das new
Schlüsselwort nicht verwendet wird, um das Objekt zu erstellen. (In der Tat wird die apply
Semantik verwendet, nicht construct
, obwohl normale Funktionen fast gleich arbeiten.)
Beim Aufruf von Reflect.construct()
hingegen zeigt der new.target
Operator auf den newTarget
Parameter, falls vorhanden, oder target
, falls nicht.
function OneClass() {
console.log("OneClass");
console.log(new.target);
}
function OtherClass() {
console.log("OtherClass");
console.log(new.target);
}
const obj1 = Reflect.construct(OneClass, args);
// Logs:
// OneClass
// function OneClass { ... }
const obj2 = Reflect.construct(OneClass, args, OtherClass);
// Logs:
// OneClass
// function OtherClass { ... }
const obj3 = Object.create(OtherClass.prototype);
OneClass.apply(obj3, args);
// Output:
// OneClass
// undefined
Spezifikationen
Specification |
---|
ECMAScript Language Specification # sec-reflect.construct |
Browser-Kompatibilität
BCD tables only load in the browser