Reflect.construct()
Reflect.construct() 靜態方法類似於 new 運算子,但以函式的形式存在。它等同於呼叫 new target(...args)。它還允許指定不同的 new.target 值。
試一試
function func1(a, b, c) {
this.sum = a + b + c;
}
const args = [1, 2, 3];
const object1 = new func1(...args);
const object2 = Reflect.construct(func1, args);
console.log(object2.sum);
// Expected output: 6
console.log(object1.sum);
// Expected output: 6
語法
Reflect.construct(target, argumentsList)
Reflect.construct(target, argumentsList, newTarget)
引數
目標-
要呼叫的目標函式。
argumentsList-
一個 類陣列物件,指定了應使用哪些引數呼叫
target。 newTarget可選-
target中new.target表示式的值。預設為target。通常(參見示例),target指定初始化物件的邏輯,而newTarget.prototype指定構造物件的原型。
返回值
target(或 newTarget,如果存在)的新例項,由 target 作為建構函式使用給定的 argumentsList 初始化。
異常
TypeError-
如果
target或newTarget不是建構函式,或者argumentsList不是物件,則會丟擲該錯誤。
描述
Reflect.construct() 提供了建構函式呼叫的反射語義。也就是說,Reflect.construct(target, argumentsList, newTarget) 在語義上等同於
new target(...argumentsList);
請注意,在使用 new 運算子時,target 和 newTarget 始終是同一個建構函式 — 但 Reflect.construct() 允許你傳遞一個不同的 new.target 值。概念上,newTarget 是呼叫 new 的函式,而 newTarget.prototype 將成為構造物件的原型,而 target 是實際執行以初始化物件的建構函式。例如,在類繼承中,new.target 也可能與當前正在執行的建構函式不同。
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {}
new B(); // "B"
Reflect.construct() 允許你使用可變數量的引數呼叫建構函式。(這也可以在普通建構函式呼叫中使用 展開語法 來實現。)
const obj = new Foo(...args);
const obj = Reflect.construct(Foo, args);
Reflect.construct() 呼叫 target 的 [[Construct]] 物件內部方法。
示例
使用 Reflect.construct()
const d = Reflect.construct(Date, [1776, 6, 4]);
d instanceof Date; // true
d.getFullYear(); // 1776
更改 new.target
如果傳遞了 newTarget,它將更改建構函式內部 new.target 的值。構造的物件將是 newTarget 的例項,而不是 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
當然,對於構造物件的原型鏈沒有嚴格的保證,因為它取決於建構函式的實現。例如,如果 target 建構函式返回一個物件,那麼該物件將成為構造的物件,無論 newTarget 的值是什麼。如果 target 是一個帶有 construct 陷阱的代理,那麼該陷阱將完全控制構造過程。
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
有效的 new.target 應該是一個帶有 prototype 屬性的建構函式,但後者並未強制執行。如果 prototype 屬性的值不是物件,則初始化物件將繼承自 Object.prototype。
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() 與 Object.create()
在引入 Reflect 之前,可以使用任意組合的建構函式和原型來構造物件,方法是使用 Object.create()。
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
然而,雖然最終結果是相同的,但過程有一個重要的區別。在使用 Object.create() 和 Function.prototype.apply() 時,在用作建構函式的函式內部,new.target 運算子將指向 undefined,因為沒有使用 new 關鍵字來建立物件。(實際上,它使用的是 apply 語義,而不是 construct,儘管普通函式碰巧執行方式幾乎相同。)
另一方面,在呼叫 Reflect.construct() 時,如果提供了 newTarget 引數,new.target 運算子將指向 newTarget 引數;如果未提供,則指向 target。
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
規範
| 規範 |
|---|
| ECMAScript® 2026 語言規範 # sec-reflect.construct |
瀏覽器相容性
載入中…