Today I noticed some weird behavior of hasOwnProperty method.

I'm on environments that fully support ES6 classes, so there is no transpilation to worry about.

The above code snippet should be returning true and false respectively, but it returns true on both.

class Stuff {
  constructor() { this.something = 'something'; }
}
class MoreStuff extends Stuff {}
const stuff = new Stuff();
const moreStuff = new MoreStuff();

console.log(Object.prototype.hasOwnProperty.call(stuff, 'something'));
console.log(Object.prototype.hasOwnProperty.call(moreStuff, 'something'));

Maybe I'm missing something here, but as long as I know, something exists on stuff and it is inherited on moreStuff, but seems that it exist on both. What I am missing?

2 Answers

0
Intervalia On Best Solutions

When, in your contsructor, you do this:

this.something = 'something';

You are putting that value into the object and not into the prototype.

Even if you subclass, the constructor adds the value of 'something' into the object.

If you want it on the prototype then it has to be made static:

class Stuff {
  static get something() {
    return 'something';
  }
  
  constructor() {
    this.ownProp = true;
  }
}
Stuff.somethingElse = 'somethingElse';

class MoreStuff extends Stuff {}
const stuff = new Stuff();
const moreStuff = new MoreStuff();

console.log(stuff.hasOwnProperty('something'));
console.log(stuff.hasOwnProperty('somethingElse'));
console.log(stuff.hasOwnProperty('ownProp'));
console.log(moreStuff.hasOwnProperty('something'));
console.log(moreStuff.hasOwnProperty('somethingElse'));
console.log(moreStuff.hasOwnProperty('ownProp'));

ownProp is still a property of the instance where something and somethingElse are properties of the Class (Prototype)

4
Pointy On

The Stuff constructor puts the "something" property directly on the constructed object. That'll be true whether you're making an instance of the parent class or the inheriting class. The prototype chain isn't involved.