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 |
浏览器兼容性
加载中…