0

Why does this say "Animal" instead of "kitty"?

// create base class Animal
function Animal(animalType) {
    this.type = animalType;
    this.sayType = function () {
        alert(this.type);
    };
}

// create derived class Cat
function Cat(myName) {
    Animal.call(this, "cat"); // cat calls the Animal base class constructor

    this.name = myName;

    this.sayName = function () {
        alert(this.name);
    };
}

Cat.prototype = Object.create(Animal); // set Cat's prototype to Animal

// instantiate a new instance of Cat
var cat = new Cat("kitty");

cat.sayName();
cat.name = "lol";
cat.sayName();

http://jsfiddle.net/dgcoffman/MguUA/5/

Daniel Coffman
  • 1,997
  • 3
  • 26
  • 34
  • 2
    your `sayType` and `sayName` functions aren't actually using prototypical inheritance _because they're not on the prototype_! You've created them as instance-local properties. – Alnitak May 02 '13 at 19:56

2 Answers2

4
Object.create(Animal); // set Cat's prototype to Animal

Yes, but to the Animal constructor function (or, to be exact: to a new object inheriting from that function object - check the docs for Object.create). That's hardly what you want - and explains your curious result of saying "Animal", as that's the Animal function's name property.

Instead, you want to build a prototype chain, so that cat instances inherit from Cat.prototype which inherits from Animal.prototype (which inherits from Object.prototype):

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

Also, for prototypical inheritance, you should but the sayName and sayType methods on the prototype object (and only once):

Animal.prototype.sayType = function() {
    alert(this.type);
};
Cat.prototype.sayName = function() { // after creation of that object, of course
    alert(this.name);
};
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • OK I admit that maybe that's what he wants to do; since the Animal prototype isn't mentioned at all, this didn't occur to me. It is however a possibility. – Pointy May 02 '13 at 19:57
  • Thanks for the response. When I do this, I get Uncaught TypeError: Object # has no method 'sayName' http://jsfiddle.net/dgcoffman/MguUA/7/ Nevermind, I was overwriting Cat's prototype after I added the sayName function to it, fixed: http://jsfiddle.net/dgcoffman/MguUA/8/ – Daniel Coffman May 02 '13 at 20:26
1

You're calling Object.create() in a way that does something different than what I bet you think it does. Try this change:

Cat.prototype = Object.create(new Animal);

The Object.create() function expects its first argument to be the object to be used as the prototype for the returned object. When you pass in the function name "Animal", that means you want the prototype object to be that function object, and not an object constructed by the function.

edit — Bergi's answer involving the direct use of the Animal prototype probably makes more sense, though from what you posted there isn't an Animal prototype object with anything interesting on it. Perhaps that's elsewhere in your code, or will be added later. Anyway if it does exist it's better to do as in his answer.

Since your "Cat" constructor is picking up the "sayType" property from the Animal constructor directly, it's not clear what you're trying to do by setting the Cat prototype.

Pointy
  • 405,095
  • 59
  • 585
  • 614
  • @Bergi huh? You're making me frantic here :-) That makes the fiddle work like I'd think it should work, but I admit that I'm not sure why overriding "name" with "kitty" doesn't work. It's also confusing because setting the prototype is silly given the `.call()` in the "Cat" constructor. – Pointy May 02 '13 at 19:55
  • I know JS better than 99% of people here but prototypical inheritance still confuses the hell out of me :( – Alnitak May 02 '13 at 19:57
  • @Alnitak lol I know; I find that I hardly ever use inheritance beyond a few simple types here and there. – Pointy May 02 '13 at 19:59
  • 1
    That doubles up the prototype chain :-) http://stackoverflow.com/q/12592913/1048572 (and sorry about mistaking you for @PointedEars :-) – Bergi May 02 '13 at 20:05
  • Yup, always inherit from the prototype, not from an instance. – Alnitak May 02 '13 at 20:07
  • Ah OK yes well that makes sense. There's a really good T. J. Crowder answer floating around out there that's got all sorts of interesting stuff about how/why to set up prototype chains. – Pointy May 02 '13 at 20:10
  • this one? http://stackoverflow.com/questions/11072556/objects-dont-inherit-prototyped-functions/11072626#11072626 – Alnitak May 02 '13 at 20:18