1

Is it possible to call a regular method from a prototype method if it's been overridden? Note that in the given example the first eat() method is called from the body of the Animal function - it is the requirement.

Animal = function(){
    this.eat();
};

Animal.prototype.eat = function() {
    console.log("All animals eat");
};

Bear = function(){
    Animal.call(this);
    this.goToSleep = function(){
        console.log("Bears go to sleep after they eat");
    }
};

Bear.prototype = Object.create(Animal.prototype);

Bear.prototype.eat = function() {
    console.log("Bears eat honey");
    this.goToSleep(); //returns 'undefined is not a function'
    //How do I invoke this.goToSleep() ?
};

var winnie = new Bear();
2
  • 1
    Why not define it as Bear.prototype.goToSleep? Commented Jan 8, 2015 at 3:08
  • You shouldn't mix the functional pattern with the prototype pattern. Either define all methods on the prototype or define them all on every instance. (The prototype pattern is preferable because it avoids duplication.) Commented Jan 8, 2015 at 3:09

1 Answer 1

1

The issue is that your bear doesn't have a goToSleep method when eat first gets invoked.

When you invoke Animal.call(this) in your Bear constructor it then calls eat - which is found on Bear.prototype and invoked. Then eat tries to invoke goToSleep but goToSleep is an instance method that you haven't added yet (remember, we are still on Animal.call we haven't reached this.goToSleep = function() yet).

Unless you have a good reason to, goToSleep should be a prototype method as well, just like eat:

Bear.prototype.goToSleep = function(){
  console.log("Bears go to sleep after they eat");
};

This will just work as you want it to.

Alternatively, if goToSleep has to be an instance method (because it needs access to some private state you create in your constructor), then simply switch the order of your Animal.call and this.goToSleep lines:

this.goToSleep = function() // etc.
Animal.call(this);
Sign up to request clarification or add additional context in comments.

2 Comments

Sean, thank you for the detailed and insightful answer. You made my day! The problem was that the real project equivalent of goToSleep() needs to access methods and properties of the base class function (i.e. Animal), therefore it can't be a prototype method. Switching the lines did the magic!
In those cases what I normally do is expose the super prototype on object via the SubConstructor.prototype.$super = SuperConstructor.prototype method. Then I can just do this.$super.someMethod.call(this, arg1, arg2, argN).

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.