Reflect.construct()
Reflect.construct(target, argumentsList[, newTarget]) Description
Reflect.construct() invokes a target constructor with a list of arguments already in array form, optionally swapping in a separate newTarget for new.target and the prototype chain. It is the reflective counterpart to the new operator, introduced in ES2015 alongside the Reflect namespace object and Proxy.
You reach for Reflect.construct() when you have constructor arguments as an array or array-like rather than as a spread, when you want to call a constructor you only have as a value, or when you need to run one constructor’s logic while exposing a different function as new.target. The third argument is the part plain new cannot do on its own.
Syntax
Reflect.construct(target, argumentsList)
Reflect.construct(target, argumentsList, newTarget)
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
target | constructor | yes | The constructor to invoke through the [[Construct]] internal slot. Must be a constructor; class declarations and function declarations work, methods and arrow functions do not. |
argumentsList | array-like object | yes | An array or array-like object whose elements are spread as positional arguments to target. Must be an object; null and undefined throw TypeError. |
newTarget | constructor | no | Defaults to target. Provides the value of new.target inside the constructor and the prototype used for the new instance (newTarget.prototype). Must be a constructor when supplied. |
Return value
A new instance of target (or newTarget when supplied), initialized by target running as a constructor with argumentsList. If the constructor returns an object explicitly, that returned object is used instead of the auto-created instance, even when newTarget is passed.
Examples
Construct from an argument array
The basic case: you already have the arguments as an array and you do not want to spread them.
function Point(x, y) {
this.x = x;
this.y = y;
}
const args = [3, 4];
const p = Reflect.construct(Point, args);
console.log(p);
// Point { x: 3, y: 4 }
console.log(p instanceof Point);
// true
This is equivalent to new Point(3, 4). The spread would work too, but when the argument list is dynamic (an arguments object, a config-derived array, a list pulled from somewhere else) Reflect.construct() keeps the call site compact and the array intact for inspection.
Build a built-in instance
Reflect.construct() works on built-ins the same way new does. Date is target, no newTarget is passed, so new.target === Date inside the constructor.
const d = Reflect.construct(Date, [1776, 6, 4]);
console.log(d instanceof Date);
// true
console.log(d.getFullYear());
// 1776
Separate target from new.target
The third argument is what Reflect.construct() adds over plain new. target runs to initialize the object. newTarget is what shows up as new.target inside target, and newTarget.prototype becomes the prototype of the result.
function OneClass() {
console.log(`new.target is ${new.target.name}`);
}
function OtherClass() {
console.log(`new.target is ${new.target.name}`);
}
const obj1 = Reflect.construct(OneClass, []);
// new.target is OneClass
console.log(obj1 instanceof OneClass);
// true
const obj2 = Reflect.construct(OneClass, [], OtherClass);
// new.target is OtherClass
console.log(obj2 instanceof OtherClass);
// true
console.log(obj2 instanceof OneClass);
// false
OneClass runs in both calls. What changes is which function “owns” the prototype of the resulting object and which name the constructor sees through new.target.
Subclass a built-in
This is the production use case for the third argument. You want a Map (or Array, Error, etc.) built by Map’s own constructor, but you want the resulting instance to carry your subclass’s prototype so it picks up your extra methods.
class MyMap extends Map {
firstKey() {
return this.keys().next().value;
}
}
const m = Reflect.construct(Map, [['a', 1], ['b', 2]], MyMap);
console.log(m instanceof MyMap);
// true
console.log(m instanceof Map);
// true
console.log(m.firstKey());
// "a"
new Map(...entries) cannot produce an instance whose prototype chain includes MyMap.prototype. Reflect.construct() is how frameworks build subclass-aware collections, error wrappers, and similar wrappers around built-ins without writing a class extends for every variant.
Constructor that returns an object
If the constructor returns an object, that object is the result, and the prototype chain follows the returned object rather than newTarget.prototype.
function OneClass() {
return { name: 'one' };
}
function OtherClass() {
return { name: 'other' };
}
const obj = Reflect.construct(OneClass, [], OtherClass);
console.log(obj.name);
// "one"
console.log(obj instanceof OneClass);
// false
console.log(obj instanceof OtherClass);
// false
The rule is the same as for new: an explicit object return overrides the auto-constructed instance, and the newTarget linkage is bypassed.
Forward from a Proxy construct trap
A construct trap should hand off to Reflect.construct() so the newTarget supplied by the caller is propagated.
function MyClass(x) {
this.x = x;
}
const P = new Proxy(MyClass, {
construct(target, args, newTarget) {
return Reflect.construct(target, args, newTarget);
}
});
const instance = new P(42);
console.log(instance.x);
// 42
console.log(instance instanceof MyClass);
// true
Replacing the body with new target(...args) would drop newTarget and break subclasses that rely on new.target matching the proxied function. This is the same reason handler.apply reaches for Reflect.apply() instead of calling through directly.
Notes
Reflect.construct()throwsTypeErroriftargetis not a constructor. Methods, arrow functions, and async functions used astargetwill not work.Reflect.construct()throwsTypeErrorifargumentsListisnullorundefined(or otherwise not an object). Pass[]for “no arguments”.Reflect.construct()throwsTypeErrorifnewTargetis supplied and is not a constructor.- The result’s prototype is
newTarget.prototypewhen the constructor does not return an object. IfnewTarget.prototypeis not an object, the new instance inherits fromObject.prototypeinstead. - Returning an object from the constructor overrides the auto-constructed instance, including the prototype linkage that
newTargetwould have set. Reflect.construct()was added in ES2015 and is available in every current browser engine and in Node.js 6+. Thecore-jspolyfill or thees-shims/reflect.constructnpm package cover older runtimes.