Reflect.construct()
Базовый уровень Широко доступно
Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с сентября 2016 года.
Статический метод 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)
Параметры
-
target - Целевая функция для вызова.
-
argumentsList - Массивоподобный объект, указывающий аргументы, с которыми должен быть вызван
target. -
newTargetНеобязательный - Значение выражения
new.targetвнутри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() вызывает внутренний метод объекта [[Construct]] для target.
Примеры
Использование 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() оператор 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
Спецификации
Совместимость с браузерами
| Десктопные | Мобильные | Серверные | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Chrome | Edge | Firefox | Opera | Safari | Chrome Android | Firefox for Android | Opera Android | Safari on iOS | Samsung Internet | WebView Android | WebView on iOS | Bun | Deno | Node.js | |
construct |
49 |
12 |
42 |
36 |
10 |
49 |
42 |
36 |
10 |
5.0 |
49 |
10 |
1.0.0 |
1.0 |
6.0.0 |
См. также
© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect/construct