Reflect.construct()

Reflect.construct() 静态方法类似于 new 操作符,但它是一个函数。它等效于调用 new target(...args)。它还允许指定不同的 new.target 值。

试一试

语法

js
Reflect.construct(target, argumentsList)
Reflect.construct(target, argumentsList, newTarget)

参数

target

要调用的目标函数。

argumentsList

一个 类数组对象,指定调用 target 时使用的参数。

newTarget 可选

new.target 操作符的值,通常指定返回对象的原型。如果 newTarget 不存在,它的值默认为 target

返回值

target(或 newTarget,如果存在)的一个新实例,由 target 作为构造函数使用给定的 argumentsList 初始化。

异常

TypeError

如果 targetnewTarget 不是构造函数,或者 argumentsList 不是对象,则抛出此异常。

描述

Reflect.construct() 提供了构造函数调用的反射语义。也就是说,Reflect.construct(target, argumentsList, newTarget) 在语义上等效于

js
new target(...argumentsList);

请注意,当使用 new 操作符时,targetnewTarget 始终是相同的构造函数 - 但 Reflect.construct() 允许您传递不同的 new.target 值。从概念上讲,newTarget 是调用 new 的函数,newTarget.prototype 将成为构造对象的原型,而 target 是实际执行以初始化对象的构造函数。例如,new.target 也有可能与当前执行的构造函数不同,例如在类继承中。

js
class A {
  constructor() {
    console.log(new.target.name);
  }
}
class B extends A {}

new B(); // "B"

Reflect.construct() 允许您使用可变数量的参数调用构造函数。(这也可以通过在正常构造函数调用中使用 展开语法 来实现。)

js
const obj = new Foo(...args);
const obj = Reflect.construct(Foo, args);

Reflect.construct() 调用 target[[Construct]] 对象内部方法

示例

使用 Reflect.construct()

js
const d = Reflect.construct(Date, [1776, 6, 4]);
d instanceof Date; // true
d.getFullYear(); // 1776

Reflect.construct() 与 Object.create() 的区别

在引入 Reflect 之前,可以使用构造函数和原型的任意组合来构造对象,方法是使用 Object.create()

js
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() 时,new.target 操作符将指向提供的 newTarget 参数,如果没有提供,则指向 target

js
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 语言规范
# sec-reflect.construct

浏览器兼容性

BCD 表格仅在启用了 JavaScript 的浏览器中加载。

另请参阅