Reflect.construct()

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

¥The Reflect.construct() static method is like the new operator, but as a function. It is equivalent to calling new target(...args). It additionally allows to specify a different new.target value.

Try it

语法

¥Syntax

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

参数

¥Parameters

target

要调用的目标函数。

argumentsList

类似数组的对象 指定应调用 target 的参数。

newTarget Optional

new.target 运算符的值,通常指定返回对象的原型。如果 newTarget 不存在,则其值默认为 target

返回值

¥Return value

target(或 newTarget,如果存在)的新实例,由 target 初始化为具有给定 argumentsList 的构造函数。

¥A new instance of target (or newTarget, if present), initialized by target as a constructor with the given argumentsList.

例外情况

¥Exceptions

TypeError

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

描述

¥Description

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

¥Reflect.construct() provides the reflective semantic of a constructor call. That is, Reflect.construct(target, argumentsList, newTarget) is semantically equivalent to:

js
new target(...argumentsList);

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

¥Note that when using the new operator, target and newTarget are always the same constructor — but Reflect.construct() allows you to pass a different new.target value. Conceptually, newTarget is the function on which new was called, and newTarget.prototype will become the constructed object's prototype, while target is the constructor that is actually executed to initialize the object. For example, new.target may also be different from the currently executed constructor in class inheritance.

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

new B(); // "B"

Reflect.construct() 允许你使用可变数量的参数调用构造函数。(这对于普通构造函数调用中的 扩展语法 也是可能的。)

¥Reflect.construct() allows you to invoke a constructor with a variable number of arguments. (This is also possible with the spread syntax in a normal constructor call.)

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

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

¥Reflect.construct() invokes the [[Construct]] object internal method of target.

示例

¥Examples

使用 Reflect.construct()

¥Using Reflect.construct()

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

Reflect.construct() vs. Object.create()

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

¥Prior to the introduction of Reflect, objects could be constructed using an arbitrary combination of constructors and prototypes using 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,尽管普通函数的操作方式几乎相同。)

¥However, while the end result is the same, there is one important difference in the process. When using Object.create() and Function.prototype.apply(), the new.target operator will point to undefined within the function used as the constructor, since the new keyword is not being used to create the object. (In fact, it uses the apply semantic, not construct, although normal functions happen to operate nearly the same.)

另一方面,当调用 Reflect.construct() 时,new.target 运算符将指向 newTarget 参数(如果提供),或者 target(如果没有)。

¥When invoking Reflect.construct(), on the other hand, the new.target operator will point to the newTarget parameter if supplied, or target if not.

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

规范

Specification
ECMAScript Language Specification
# sec-reflect.construct

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看