Reputation: 2263
In the following I'm trying to create a subclass of Object which behaves like Object does in terms of creating instances by using 'new'. I would of course add more methods to my subclass, but below shows the problem I have calling the super-constructor from within my constructor.
Why does an instance of my class Sub not have the field 'x' like a plain Object does when created in the same way with 'new' with the same argument?
class Sub extends Object
{ constructor (anObject)
{ super(anObject);
}
}
var ob = new Object ({x: 123} );
var sub = new Sub ({x: 123} );
console.log( ob.x ); // -> 123
console.log( sub.x); // -> undefined
Upvotes: 2
Views: 728
Reputation: 528
While I find this behavior confusing myself (and thus cannot answer the deeper "why it was designed like this"), it seems to be documented behavior. In MDN it says:
When Object() is implicitly called via super() in the constructor of a class that extends Object, it initializes a new object with new.target.prototype as its prototype. Any value passed to super() is ignored — for example, even if you pass a number, the this value inside the constructor does not become a Number instance.
The specs say:
This function performs the following steps when called:
- If NewTarget is neither undefined nor the active function object, then a. Return ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%").
- If value is either undefined or null, return OrdinaryObjectCreate(%Object.prototype%).
- Return ! ToObject(value).
To my understanding, while the last one is the one you get when calling new Object(obj)
, you get the first one when calling super(obj)
.
Thus the behavior is not only in Node, but also in all spec respecting browsers (I've verified in Firefox 115 and Chromium 115).
Upvotes: 0
Reputation: 26537
Basically, because Object
is special and plays by different rules, since it's pretty much the most foundational construct in JavaScript.
Instead of extending Object
, just create it with no super class (since it'll be an Object anyways) and use Object.assign(this, obj)
to assign all of the properties to the newly created object.
class Sub {
constructor(obj) {
Object.assign(this, obj);
}
}
console.log(new Object({a: 1}));
console.log(new Sub({a: 1}));
Upvotes: 6