Panu Logic
Panu Logic

Reputation: 2263

Calling super() inside constructor of JavaScript ES6 class which extends Object

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

Answers (2)

Sebastian
Sebastian

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:

  1. If NewTarget is neither undefined nor the active function object, then a. Return ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%").
  2. If value is either undefined or null, return OrdinaryObjectCreate(%Object.prototype%).
  3. 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

samanime
samanime

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

Related Questions