0

I am having trouble to understand something. I have been looking for a while about the differences but I can't seem to find the answer I am looking for.

I am trying to learn OOP javascript and every tutorial I read there seems to be a different way of doing inheritance and it is often explained in a very complicated way. The problem I am stuck on now has to do with creating methods for an object, I am using the code from the Mozilla developer documentation.

You will see in the large code block below that I tried to add a jump method in the Person like this:

Person.prototype = {
  jump: function() {
    console.log("Jumping")
  }
}

This doesn't work it basically breaks the entire class telling me that student1.walk is not a function. However if I change the declaration of the method to

Person.prototype.jump = function() {
    console.log("Jumping");
}

Everything works like it should when I call the methods. From a personal style standpoint though I like the first way of creating methods because I don't have to keep repeating the Person.prototype portion I can just keep adding a comma followed by my method declaration. I am wondering what the difference is between these two ways of creating methods because I can't find the answer anywhere. I want to understand why it breaks using the first method as well.

  var Person = function(firstName) {
      this.firstName = firstName;
    };

    Person.prototype.walk = function(){
      console.log("I am walking!");
    };

    Person.prototype = {
      jump: function() {
        console.log("Jumping");
      }
    }

    Person.prototype.sayHello = function(){
      console.log("Hello, I'm " + this.firstName);
    };

    function Student(firstName, subject) {

      Person.call(this, firstName);

      this.subject = subject;
    }

    Student.prototype = Object.create(Person.prototype); // See note below

    Student.prototype.constructor = Student;

    Student.prototype.sayHello = function(){
      console.log("Hello, I'm " + this.firstName + ". I'm studying "
                  + this.subject + ".");
    };

    Student.prototype.sayGoodBye = function(){
      console.log("Goodbye!");
    };

    var student1 = new Student("Janet", "Applied Physics");
    student1.sayHello();
    student1.walk();
    student1.sayGoodBye();
    student1.jump();
2
  • 1
    Person.prototype = {...} overrides the prototype. You can do Object.assign(Person.prototype, {...}) Commented Mar 9, 2016 at 21:16
  • Instead of assing new object into prototype you have to assign a new method in your case jump Commented Mar 9, 2016 at 21:18

4 Answers 4

7

The issue is that you're overriding the entire prototype chain by calling Person.prototype = {}. This makes the other methods vanish, because they were taken out of the chain by resetting it.

It's like any other variable

let x = 5; //5
x = 6; // 6

It's a simple assignment statement re-assigning your prototype chain.

Sign up to request clarification or add additional context in comments.

Comments

3

Just compare the two statements:

Person.prototype = {
  jump: function() {
    console.log("Jumping");
  }
};

Here you're setting the prototype to a new object literal. In the next statement:

Person.prototype.jump = function() {
    console.log("Jumping");
};

You're setting the jump property of the the prototype to a function.

If you want to add all functions at once, declare the prototype once:

Person.prototype = {
  jump: function() {
    console.log("Jumping")
  },
  walk: function(){
    console.log("I am walking!");
  },
  sayHello: function(){
    console.log("Hello, I'm " + this.firstName);
  }
};

The difference between them is simply a matter of when the method is added to the prototype. I generally prefer adding all of my functionality to a prototype at once, so that I know where in the code I made the sayHello method. I do occasionally use the second method, if I need to redefine a method in light of new information. But that's very rare.

2 Comments

In your example, this.firstName is undefined. Make sure you include the local variables!
Meh, so it logs "Hello I'm undefined"... It's not that far off ;)
2

Never replace the prototype of a constructor with a different object, unless you know what you are doing.

It has these problems:

  • Instances created before the change will no longer be considered instances by instanceof, and they won't inherit properties from the new object.
  • Instances creates after the change won't inherit properties from the old object.
  • The old object might have some data you didn't explicitly set, e.g. a constructor property or the internal [[Prototype]]. This will be lost unless you copy it to the new object.

If you just want to add multiple properties to the prototype without repeating it each time, use Object.assign:

Object.assign(Person.prototype, {
  jump: function() {
    console.log("Jumping");
  },
  sayHello = function(){
    console.log("Hello, I'm " + this.firstName);
  }
});

3 Comments

Just want to clarify. prototype and instanceof has nothing similar. instanceof works with constructor not with prototype
@The instanceof uses [[HasInstance]], which checks whether an object inherits from the prototype of a constructor. constructor is not involved at all.
yeap my typo, i meant prototype.constructor. Thanks
1

OOP in javascript is ugly to look at. I would use a class library like ds.oop. Its similar to prototype.js and others. makes multiple inheritance very easy and its minimalist. (only 2 or 3 kb) Also supports some other neat features like interfaces and dependency injection

/*** multiple inheritance example ***********************************/

var Runner = ds.class({
    run: function() { console.log('I am running...'); }
});

var Walker = ds.class({
    walk: function() { console.log('I am walking...'); }
});

var Person = ds.class({
    inherits: [Runner, Walker],
    eat: function() { console.log('I am eating...'); }
});

var person = new Person();

person.run();
person.walk();
person.eat();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.