Skip to content

Commit

Permalink
Add example for Reflect.construct newTarget parameter (mdn#35996)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josh-Cena authored Oct 1, 2024
1 parent 9707395 commit dc8acd5
Showing 1 changed file with 69 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Reflect.construct(target, argumentsList, newTarget)
- `argumentsList`
- : An [array-like object](/en-US/docs/Web/JavaScript/Guide/Indexed_collections#working_with_array-like_objects) specifying the arguments with which `target` should be called.
- `newTarget` {{optional_inline}}
- : The value of [`new.target`](/en-US/docs/Web/JavaScript/Reference/Operators/new.target) operator, which usually specifies the prototype of the returned object. If `newTarget` is not present, its value defaults to `target`.
- : The value of the [`new.target`](/en-US/docs/Web/JavaScript/Reference/Operators/new.target) expression inside `target`. Defaults to `target`. Generally ([see example](#changing_new.target)), `target` specifies the _logic_ to initialize the object, while `newTarget.prototype` specifies the _prototype_ of the constructed object.

### Return value

Expand Down Expand Up @@ -76,6 +76,74 @@ d instanceof Date; // true
d.getFullYear(); // 1776
```

### Changing new.target

If `newTarget` is passed, it changes the value of `new.target` inside the constructor. The constructed object will be an instance of `newTarget`, not `target`.

```js
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
```

Of course, there's no strong guarantee about the prototype chain of the constructed object, as it depends on the constructor's implementation. For example, if the `target` constructor returns an object, then that object will be the constructed object, regardless of the `newTarget` value. If `target` is a proxy with a `construct` trap, then the trap fully controls the construction process.

```js
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
```

A valid `new.target` should be a constructor function with a [`prototype`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype) property, but the latter is not enforced. If the `prototype` property's value is not an object, the initialized object will inherit from `Object.prototype`.

```js
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() vs. Object.create()

Prior to the introduction of `Reflect`, objects could be constructed using an arbitrary combination of constructors and prototypes using {{jsxref("Object.create()")}}.
Expand Down

0 comments on commit dc8acd5

Please sign in to comment.