3

My question is simply:

How do I set up the prototype of a class that inherits from another class's prototype?

My code below works until I try to call Pierre.mySkill(), at which point the console says that the function is undefined.

My reason for this, theoretically, is to be able to create instances of Pirault, and also instances of Person, and be able to add to Pirault's prototype without having to add to Person's.

function Person (name, age){
    this.name = name;
    this.age = age;
}

Person.prototype.info = function(){
    console.log('I am '+this.name+' and I am '+this.age+' years old.');
};

function Pirault (){
    this.skill = arguments[2];

    Person.apply(this, arguments);
}

Pirault.prototype.mySkill = function(){
    console.log('My skill is '+this.skill);
}

Pirault.prototype = Object.create(Person.prototype);
Pirault.prototype.constructor = Pirault;

var Pierre = new Pirault('Pierre', 30, 'Programming');
3
  • 1
    So skill is "Pierre"? Commented Sep 12, 2014 at 23:44
  • woops! Thanks for catching that, I meant to update it before I posted. Commented Sep 12, 2014 at 23:47
  • 1
    Here is a simplified version of your problem: var foo = {}; foo.name = 'foo'; foo = {}; console.log(foo.name);. It should be pretty obvious why foo.name returns undefined. Commented Sep 13, 2014 at 0:10

2 Answers 2

2

Organize your code so that all the prototype methods are defined after the prototype object is created. For example:

Pirault.prototype = Object.create(Person.prototype);
Pirault.prototype.constructor = Pirault;

Pirault.prototype.mySkill = function(){
    console.log('My skill is '+this.skill);
}

Demo. As it stands, you correctly define a method on the prototype - but then lose it, when an object (created by Object.create) becomes a new Pirault.prototype.

Sign up to request clarification or add additional context in comments.

Comments

2

As an alternative approach you don't need constructors to do this. All you need in modern browsers are objects and Object.create:

var Person = {
  info: function() {
    console.log('I am '+ this.name +'and I am '+ this.age +' years old.')
  }
}

var Pirault = Object.create(Person)
Pirault.mySkill = function() {
  console.log('My skill is '+ this.skill)
}

var pierre = Object.create(Pirault)
pierre.name = 'Pierre'
pierre.age = 30
pierre.skill = 'Programming'

pierre.mySkill() //=> My skill is Programming

console.log(Pirault.isPrototypeOf(pierre)) //=> true
console.log(Person.isPrototypeOf(pierre)) //=> true

7 Comments

This approach works well if all the base objects are 'interfacial' (ahem) - i.e., only contain methods to work on. Otherwise one has to instantiate them too, and that can get messy, in my opinion. Still, nice approach, +1 from me. )
ONE THOUSAND THANK YOUS. If I could upvote you more than once, I would. You can't imagine how many articles I read promoting the Class/constructor/new-based approach and I always felt like something was "not quite right"...
Actually, there's more than one way to organize the objects' hierarchy - for example, mixins (Base.call(this)).
@papiro It's really a long talk, and I feel I won't be able to explain it in the SO answer (let alone in the comment). Note the difference, though: in your case, you didn't assign properties on pierre - you just passed it up into the base's constructor class with Person.apply(this, arguments) line. With the approach given in this answer, it's not so - setting up properties on Object's instances is the responsibility of the client, the one that creates that instance.
@papiro May I recommend you reading this wonderful book of Addy Osmani? In my opinion, it explains the difference - and potential use-cases - for different Creational patterns in JS pretty darn well. )
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.