3

When Im reading this,It tells me that "A new instance of the given target, created by calling it (or newTarget, if present) as a constructor with the given arguments." But in reality, it is not the case at all. Here is an example:

function Parent() {
  this.parent = "Parent"
  console.log("This is parent.")
}
function Child() {
  this.child = "Child"
  console.log("This is child.")
}
var result = Reflect.construct(Parent, [], Child);
console.log(result)

The output looks like this:

enter image description here

This is acting so weird to me because base on the doc, when we put Child as new target parameter in Reflect.construct, it should use constructor of Child to make a new instance, but the log shows "This is parent." is printed and property of Parent is saved while at the same time constructor is of Child(). How could this be possible? Can someone please explain what is happening behind the scene? This is driving me crazy, I really want to know how javascript does this. Thank you so much guys.

Panda World
  • 1,704
  • 1
  • 20
  • 28
  • "*it should use constructor of Child to make a new instance*" - no, it only calls the constructor that you pass in as `target` (the first argument). It uses the newtarget to derive the inheritance hierarchy only. `Reflect.construct` can be used to desugar `super()` calls in `class` constructors. – Bergi May 15 '18 at 11:35
  • Hi Bergi, I did see your answer on that page but pardon me as im super new to javascript so I don't fully understand all of it. Like the [[NewTarget]] property(does double brackets means it is an inner property/method? but i only see properties like __proto__?) cannot be found in the output graph, it makes me more confused. So base on what you said, the [[NewTarget]] holds the child constructor and eventually it makes the __proto__ point to prototype of child() right? At least thats what I get when including the output graph. Please correct me if im wrong. – Panda World May 15 '18 at 12:38
  • Actually I bookmarked that page since I could not fully understands your answer and hopefully one day will do. – Panda World May 15 '18 at 12:39
  • Yes, double brackets mean that it's an internal property. In this case, an internal property of an internal object, so it's pretty much irrelevant - all that matter is that you can use the `new.target` "keyword" to access it inside a constructor's scope, similar to how you can use the `this` keyword in a function's scope. "*the [[NewTarget]] holds the child constructor and eventually it makes the instance [[prototype]] point to `child.prototype` right?*" - yes. – Bergi May 15 '18 at 12:45
  • It is not full duplicate, it is just similar, but about Reflect. – user1742529 Apr 14 '21 at 05:49

1 Answers1

2

I'd say the documentation is somewhat misleadingly worded. What seems to be happening is that construct() invokes the first the first argument as the constructor (i.e. to initialize the object), but uses the last argument as the prototype (i.e. the actual "class" of the object). In your case, result instanceof Child returns true, but result instanceof Parent returns false.

So, the result of Reflect.construct(target, args, newTarget) seems to be equivalent to this:

var result = Object.create(newTarget.prototype);
target.apply(result, args);

However, there is one significant difference: in the above example, the new.target operator within either function will return undefined, since you're not using the new keyword to create the object. When you use Reflect.construct(), on the other hand, new.target will point to newTarget (hence the name, I suppose) -- probably because, in the end, the resulting object will belong to that class.

(Note: I have since requested an edit to the MDN page about Reflect.construct() to include these details)

Máté Safranka
  • 4,081
  • 1
  • 10
  • 22
  • Hi Máté Safranka, your answer is fantastic. It confused me the most actually when I saw the data structure output, cause I could not find new.target property there. Is it some kind of hidden property in the Function? – Panda World May 15 '18 at 12:59
  • No, `new.target` is a special keyword, kind of like `this`; it's always available, and refers to different things depending on the invocation context. Specifically, it refers to the function that's currently being invoked as a constructor. – Máté Safranka May 15 '18 at 13:19
  • `Reflect.construct(OneClass, args, OtherClass)` === `OneClass.apply(Object.create(OtherClass.prototype), args)` ? – user1742529 Apr 14 '21 at 08:11