0

At the moment, I try to understand the Javascript prototype object. Following situation:

// new Person object
function Person () {
    this.greeth = function() {
        console.log("Good morning, " + this.name);
    };
};

// add new function to Person.prototype for inheritance
Person.prototype.sayWeight = function() {
    console.log(this.weight);
};

// create new friend object
var friend = {
    forename: "Bill",
    lastname: "Gates",
    weight: 78,
    sayhello: function() {
        console.dir("Hello " + this.forename + ' ' + this.lastname);
    }
};

// assign Person.prototype to friend.prototye (inheritance)
friend.prototype = Person;

console.dir(friend);

Now my question: I assign the Person Object to my friend.prototype . For my understanding, "friend" should have all the functions of Person.prototype (i.e. sayWeight() cause of friend.prototype = Person; ). But the only function I can call is friend.sayhello. In my output (console.dir(friend);), I can see the sayWeight() function, but when I call it, I get an error (TypeError: Object #<Object> has no method 'sayWeight')

Can you explain this behavior? Why can't I access the sayWeight() function?

=========================================================

Another question:

function Person() {
    this.name = "Bill Gates";
    this.weight = 78;
    this.sayHello = function() {
        console.log("Hello " + this.name);
    }
}

Person.prototype.sayWeight = function() {
    console.log(this.weight);
}

var friend = new Person();

What is the difference between the sayWeight and the sayHello function? The sayWeight function is in the prototype-object of Person - okay, but what advantages do I have from prototype in this case?

3
  • 1
    I wrote this article which might help you understand the differences. Commented Oct 12, 2013 at 9:08
  • 1
    A confusing thing in javascript is that x.prototype is not "the prototype of x". Commented Oct 12, 2013 at 9:18
  • I have edited my answer to cover your last question. Commented Oct 12, 2013 at 13:21

2 Answers 2

2

Can you explain this behavior? Why can't I access the sayWeight() function?

Because you can't change the prototype of an object after you create it. You are setting the prototype property, but the internal prototype reference that is used by the javascript interpreter, namely __proto__ is still the one used in effect, and currently __proto__ is referring to Object.prototype.

If you changed this line friend.prototype = Person; to this one friend.__proto__ = Person.prototype; then everything will work.

If your browser supports ES5 then you can use Object.create() to create objects that inherit from a given prototype, or you can use a workaround adopted from the book Javascript: The Good Parts, and twisted a little by David Flanagan in his book: Javascript The Definitive Guide:

// inherit() returns a newly created object that inherits properties from the
// prototype object p. It uses the ECMAScript 5 function Object.create() if
// it is defined, and otherwise falls back to an older technique.
function inherit(p) {
    if (p == null) throw TypeError(); // p must be a non-null object
    if (Object.create) // If Object.create() is defined...
        return Object.create(p); // then just use it.
    var t = typeof p; // Otherwise do some more type checking
    if (t !== "object" && t !== "function") throw TypeError();
    function f() {}; // Define a dummy constructor function.
    f.prototype = p; // Set its prototype property to p.
    return new f(); // Use f() to create an "heir" of p.
}

NOTE __proto__ isn't a standardized property and shouldn't be used in production code, or as @alex noted in his comment it is on the way of standardization.

NOTE 2: As @thg435 mentioned in his comment, an alternative to using the __proto__ property is using Object.setPrototypeOf() which is standardized in ES6.

EDIT TO COVER LAST QUESTION

What is the difference between the sayWeight and the sayHello function ?

The difference is that now each new instance of Person (for example new Person()) will have a distinct sayHello() function, but a shared sayWeight() function.

var friend = new Person();
var anotherFriend = new Person();

console.log(friend.sayHello === anotherFriend.sayHello); // OUTPUTS FALSE
console.log(friend.sayWeight === anotherFriend.sayWeight); // OUTPUTS TRUE

what advantages do I have from prototype in this case?

Well less memory, code reuse across all instances of person, and if you already have one or more person objects and you want to add a new method to all of them without modifying each one in turn then you can add that method to the prototype and they will all inherit from it.

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

5 Comments

Remember that proto is non standarized feature, and should be not used.
@KarolSikora You are correct, I just wanted to explain what is going on underneath.
@KarolSikora It is being standardised.
@thg435 Added a note about that. Thank You.
1

Person doesn't inherit Person.prototype, only instances of Person do. Further, with a normal Object say foo = {}, foo.prototype is just a normal property. You'd either need a constructor or to create the initial object defining it as having a specific prototype.

What you actually want is

friend = Object.create(Person.prototype);
// or, for older browsers
friend = new Person();
// or some Object.create shim
/* which gives you
friend inherits Person.prototype
       inherits Object.prototype */

This sets up the prototype chain. If you want to create many friends, it may be better to set up a new constructor Friend, which has Friend.prototype = Object.create(Person.prototype);. This also protects Person.prototype from if you want to add properties to Friend.prototype. Then you would have

(instanceof) Friend inherits Friend.prototype
                    inherits Person.prototype
                    inherits Object.prototype

2 Comments

So I have to create a new Person()-Object? Something like: var friend = new Person(); friend = { forename: "Bill", lastname: "Gates", weight: 78, sayhello: function() { console.dir("Hello " + this.forename + ' ' + this.lastname); } };
@Newbie no, after creating the object you would set with friend['forename'] = 'Bill';, etc

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.