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

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.