Alan Souza Alan Souza - 3 years ago 128
Javascript Question

Prototypical inheritance: how to get instanceof?

After watching this video I learned about a nice way to implement inheritance with Javascript: prototypical inheritance. This method uses Object.create/Object.assign to create a new object based on another instance. This seems very interesting given that it is very easy to understand what is going on. For example:



const human = {
species: 'human',
create: function(values) {
const instance = Object.create(this);
Object.assign(instance, values);
return instance;
},
sayName: function() {
console.log(`Hi, my name is ${this.name}`);
},
saySpecies: function() {
console.log(`Hi, I'm a ${this.species}`);
}
}

const musician = human.create({
species: 'musician',
playInstrument: function() {
console.log(`I'm a musician and I play ${this.instrument}`);
}
});

const aHuman = human.create({ name: 'Paul' });
aHuman.sayName();
aHuman.saySpecies();

const aMusician = musician.create({ name: 'David', instrument: 'Guitar' });
aMusician.sayName();
aMusician.saySpecies();
aMusician.playInstrument();

// how to check if musician is an instance of human?
console.log(musician instanceof human);





With the classical inheritance, I can use
instanceof
to know if a given object has a given proto in its chain (e.g.
musician instanceof Human
).

This is what the proto chain looks like, which seems very similar to the one created with the
new
operator.

enter image description here

Question
How to achieve the same thing with prototypical inheritance?

Answer Source

There are two main problems with your attempt:

  • The RHS of instanceof has to be a function, so your types have to be built on top of functions.
  • You are not distinguishing between static/type methods and instance methods. create is a type method. sayName is an instance method.

The follow should work as you are expecting.

function Human(){}

Object.assign(Human, {
  create: function(values) {
    let newObj = Object.create(this.prototype);
    return Object.assign(newObj, values);
  }
});

Object.assign(Human.prototype, {
  species: 'human',
  sayName: function() {
    console.log(`Hi, my name is ${this.name}`);
  },
  saySpecies: function() {
    console.log(`Hi, I'm a ${this.species}`);
  }
});

function Musician(){}

Object.assign(Musician, Human);

Musician.prototype = Human.create({
  species: 'musician',
  playInstrument: function() {
    console.log(`I'm a musician and I play ${this.instrument}`);
  }
});

const aHuman = Human.create({ name: 'Paul' });
aHuman.sayName();
aHuman.saySpecies();

const aMusician = Musician.create({ name: 'David', instrument: 'Guitar' });
aMusician.sayName();
aMusician.saySpecies();
aMusician.playInstrument();

// how to check if musician is an instance of human?
console.log(aMusician instanceof Human);

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download