1

I have the following functions which define an inheritance chain.

function Person(name,age) {

    this.name = name;
    this.age = age;
}

Person.prototype.dance = function () {
    console.log("Person is dancing");
};

var Programmer = function (name, age, skills)
{   
    Programmer.prototype = new Person(name, age);;
    this.skills = skills;
};



Programmer.prototype.talkShit = function () {
    console.log("The programmer " + this.name+ " is talking shit....");
};

and I try to call dance() method on a programmer object

  var programmerX = new Programmer("Pro A", 30, "Talking crap");

        programmerX.dance();

However, an error happened saying that dance() is undefined. I'm just wondering why? What's wrong?

Toan Nguyen
  • 11,263
  • 5
  • 43
  • 59

3 Answers3

2

There's a couple issues with how you're defining the prototype inheritance chain. You want to assign the Programmer prototype outside of the constructor and you'll likely want to be using Object.create instead of new. You also want to call the "super" constructor in your Programmer constructor by calling Person.call(this, name, age). I'd recommend an approach like this:

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

Person.prototype.dance = function() {
    console.log("Person is dancing");
};

var Programmer = function(name, age, skills) {   
    Person.call(this, name, age);
    this.skills = skills;
};

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

Programmer.prototype.talkShit = function () {
    console.log("The programmer " + this.name+ " is talking shit....");
};
Marc Baumbach
  • 10,323
  • 2
  • 30
  • 45
  • 1
    For additional information as to choosing between `Object.create` vs `new`, see http://stackoverflow.com/questions/13040684/javascript-inheritance-object-create-vs-new – Marc Baumbach Mar 12 '14 at 04:57
1

You can extend your Object prototype with

Programmer.prototype = new Person();
Programmer.prototype.constructor = Programmer;

But obviously, an empty constructor will be called, so you will have to call this manually afterwards from within your Programmer object

Person.call(this, name, age);

Giving you

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

Person.prototype.dance = function () {
    console.log("Person is dancing");
};

function Programmer(name, age, skills)
{
    Person.call(this, name, age);
    this.skills = skills;
};
Programmer.prototype = new Person();
Programmer.prototype.constructor = Programmer;

Testing this with

var programmerX = new Programmer("Alice", 30, "Something");
var programmerY = new Programmer("Bob", 25, "Something else");
console.log(programmerX);
console.log(programmerY);
programmerX.dance();

We'll get

{ name: 'Alice', age: 30, skills: 'Something' }
{ name: 'Bob', age: 25, skills: 'Something else' }
Person is dancing
kba
  • 19,333
  • 5
  • 62
  • 89
1

I just want to point out how easy this is in TypeScript:

class Person {
    constructor(public name: string, public age: number) {
    }
    dance() {
        console.log('Person is dancing');
    }
}

class Programmer extends Person {
    constructor(name: string, age: number, public skills: string) {
        super(name, age);
    }
    talkShit() {
        console.log('The programmer ' + this.name + 'is talking shit....');
    }
}

var programmerX = new Programmer('Pro A', 30, 'Talking crap');

Which generates the JavaScript for you, which you can see on The TypeScript Playground here.

If you're going to be doing a lot of inheritance, it'll make your code a lot more readable.

jedmao
  • 10,224
  • 11
  • 59
  • 65