2

If I run this piece of JavaScript code in Firefox:

function Human() {

}

function Engineer(diploma) {
    this.diploma = diploma;
}

Engineer.prototype = new Human();// Line A1
Engineer.prototype.constructor = Engineer;
Engineer.prototype.getDiploma = function() {
    alert(this.diploma);
};
var engineer = new Engineer("Bridges and Roads");
engineer.getDiploma();
var human = new Human();
human.getDiploma(); // Line A2

the line marked as "A2" will generate an error in the Firefox console:

TypeError: human.getDiploma is not a function

Note also that, on line A1, I've used "new" to simulate that Engineer inherits from Human. This can be tested in the following JSFiddle:

http://jsfiddle.net/RMWdh/1/

Now I change the A1 line like so:

function Human() {

}

function Engineer(diploma) {
    this.diploma = diploma;
}

Engineer.prototype = Human.prototype;// Line B1
Engineer.prototype.constructor = Engineer;
Engineer.prototype.getDiploma = function() {
    alert(this.diploma);
};
var engineer = new Engineer("Bridges and Roads");
engineer.getDiploma();
var human = new Human();
human.getDiploma(); // Line B2

Note that A1 line has been replaced by the B1 line. The rest of the code is the same. This time, if I run it, there's no error in the Firefox console, but I will get one alert saying "Bridges and Roads" (which is the call to engineer.getDiploma()), and another alert saying "undefined" (which is the result of the B2 line). This can also be checked on JSFiddle, here:

http://jsfiddle.net/RMWdh/2/

My question is: why this difference? What's the difference between doing this:

 Engineer.prototype = new Human();

and this:

 Engineer.prototype = Human.prototype;
2
  • possible duplicate of Why can't I call a prototyped method in Javascript? Commented Nov 17, 2013 at 13:24
  • Hi, it's a little late but if you want diploma and getDiploma to be members of Human you should define diplama in the Human body with this.deploma, define getDiploma on Human.prototype and get ownership of diploma when creating an Engeneer instance by adding Human.call(this,arguments); in the Engeneer constructor function. Change the signature of Human to Human(diploma). More info on prototypes and inheritance can be found here: stackoverflow.com/a/16063711/1641941 Commented Nov 17, 2013 at 13:41

2 Answers 2

2

The latter simply copies the reference, making both "Engineers are Humans" and "Humans are Engineers" true. That isn't typically the desired effect.

Engineer.prototype = Human.prototype;
var human = new Human();
/*
  engineer ->
    (Engineer.prototype & Human.prototype) ->
      Object.prototype
*/

var human = new Human();
console.log('getDiploma' in human);     // true
console.log(human instanceof Engineer); // true

The former, on the other hand, only establishes that "Engineers are Humans." This allows Engineers to keep their own identity and logic separate from other Humans. In this case, including .getDiploma().

Engineer.prototype = new Human();
var engineer = new Engineer("Bridges and Roads");
/*
  engineer ->
    Engineer.prototype ->
      Human.prototype ->
        Object.prototype
*/

var human = new Human();
console.log('getDiploma' in human);     // false
console.log(human instanceof Engineer); // false

You can also use Object.create() to establish the prototype chain without needing to call the constructor:

Engineer.prototype = Object.create(Human.prototype);
Sign up to request clarification or add additional context in comments.

3 Comments

Ok, but: a. why, in the latter case, do I get undefined when calling human.getDiploma() ? and b. does it mean that each time I do "new Human" a new clone of its prototype is made?
@ShivanDragon A) You see undefined because human.getDiploma() is attempting to alert(human.diploma), which was never set. An object can inherit from Engineer.prototype without ever calling the Engineer() constructor function -- Object.create(Engineer.prototype) included.
@ShivanDragon B) Not a clone per-se, but they do inherit directly from Human.prototype, yes. Inheritance in JavaScript is managed through [[Prototype]] properties (exposed as __proto__ in some browsers). When encountering a property accessor/member operator, the JavaScript engine can follow the chain of [[Prototype]] references until it finds the property or the end of the chain.
0

Your problem is prototype inheritance:

with line A2 you're calling

human.getDiploma()

but getDiploma doesn't appear on the prototype of Human.

Engineer inherits the object Human as it's prototype, but Human doesn't inherit anything from Engineer.

if you made getDiploma() a method on Human, you'd have this working:

function Human() {

}

Human.prototype.getDiploma = function() {
    alert(this.diploma);
};

function Engineer(diploma) {
    this.diploma = diploma;
}

Engineer.prototype = Human.prototype;// Line B1
Engineer.prototype.constructor = Engineer;

var engineer = new Engineer("Bridges and Roads");
engineer.getDiploma(); // "Bridges and Roads"
var human = new Human();
human.getDiploma(); // "undefined"

Comments

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.