5

It seems as though I am finally understanding JavaScript inheritance and how it should be done properly. Here is my code:

function Human(eyes) {
    this.eyes = eyes ? "Not blind" : "Blind";
}
Human.prototype.canSee = function () {
    return this.eyes;
};
function Male(name, eyes) {
    Human.call(this, eyes);
    this.name = name;
}
Male.prototype = Object.create(Human.prototype);
var Sethen = new Male("Sethen", true);
console.log(Sethen.canSee()); //logs "Not blind"

From what I understand, using Object.create to create your prototype object for inheritance is much better than using the new keyword. This raises a couple questions in my head.

  1. In the Male.prototype = Object.create(Human.prototype) would the prototype chain be Male.prototype --> Human.prototype --> Object.prototype --> null?
  2. In the Male constructor where I use Human.call(this, eyes); to call a super class, I have to pass eyes again in the Male constructor to pass it to the Human constructor. This seems like a pain, is there an easier way to do this?
  3. How come sometimes I see code like Male.prototype = new Human(); ... This seems to be incorrect. What is actually happening when we do that??
Sethen
  • 11,140
  • 6
  • 34
  • 65
  • 1
    Have you seen this http://stackoverflow.com/questions/13040684/javascript-inheritance-object-create-vs-new and this http://stackoverflow.com/questions/4166616/understanding-the-difference-between-object-create-and-new-somefunction-in-j ??? – rafaelcastrocouto Jul 18 '13 at 18:05
  • No I haven't. I will take a look though. – Sethen Jul 18 '13 at 18:27

1 Answers1

3

To answer your questions:

  1. That's correct. When you set Male.prototype = Object.create(Human.prototype) you set the prototype chain as Male.prototype --> Human.prototype --> Object.prototype --> null. Then when you create var Sethen = new Male the instance (Sethen) inherits from this prototype chain.
  2. No, you need to manually pass the parameters to the base constructor function. If you want to could set this.eyes = eyes ? "Not blind" : "Blind" within the Male function itself but that would just be code duplication. What you're doing is correct.
  3. That was the old way of doing things (before Object.create was standardized). I would recommend that you don't use it. For most cases it's the same as the new method. However using this method you also get unwanted properties like eyes on Male.prototype.

When we do Male.prototype = new Human we create a new instance of Human and assign it to Male.prototype. Hence the prototype chain is Male.prototype --> Human.prototype --> Object.prototype --> null. However we also get the property Male.prototype.eyes which we don't require. That should only belong to the instance of Male.

I would recommend you read my blog post. It's a really good primer on prototypal inheritance: Aadit M Shah | Why Prototypal Inheritance Matters

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
  • Thanks man! This cleared up things for me. I assumed that we were getting some unwanted properties like `eyes` as well, but wasn't sure. – Sethen Jul 18 '13 at 18:27
  • Before Object.create helper functions were used: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 (still are if you want to support IE 8) In these helper functions the constructor can be set to the right function after setting inheritance as well. You still need to do this if you're planning to use the `constructor` property. – HMR Jul 19 '13 at 01:08
  • 1
    @HMR Ah. Well, the only helper function I use nowadays is [`augment`](https://github.com/javascript/augment). It uses `Object.create` but you can implement it without using `Object.create` as well. – Aadit M Shah Jul 19 '13 at 02:21