Domanda

Is prototype inheritance behaving differently based on the type? Is the contextual reference THIS working different in these two cases? Why in this examples, one is accessing to the prototype and the other one is creating a new property to the object?

var Player = function(){};

Player.prototype.name = '';
Player.prototype.set_name = function(name){this.name = name;}

var p1 = new Player();
var p2 = new Player();

p1.set_name('Johanna');

Value return by these two:

// Checking object properties
>p1
Player {name: "Johanna", set_name: function}

>p2
Player {name: "", set_name: function}

// Checking prototypes
>p1.__proto__
Object {name: "", set_name: function}

>p2.__proto__
Object {name: "", set_name: function}

But if I do the Player with name as an object property, the function set_name is modifying the prototype.

var Player = function(){};

Player.prototype.name = {};
Player.prototype.set_name = function(name){this.name['first_name'] = name;}

var p1 = new Player();
var p2 = new Player();

p1.set_name('Andrew');

Value return by these two:

// Checking object properties
>p1.name
Object {first_name: "Andrew"}

>p2.name
Object {first_name: "Andrew"}

// Checking prototypes
>p1.__proto__.name
Object {first_name: "Andrew"}

>p2.__proto__.name
Object {first_name: "Andrew"}

Why is this happening? What concept(s) am I missing?

È stato utile?

Soluzione

Inheritance chain

When you create an object with a constructor function, the inheritance chain goes like this, for lookup.

  1. The current object will be searched.

  2. Prototype of the parent will be searched.

  3. Prototype of the parent's parent will be searched.

    ...

And finally the global object will be searched. If it is not found anywhere, undefined will be returned. If the value being looked up is found in any of these levels, it will be returned immediately.

Note: Assignments won't go up the inheritance chain. If you assign a value to an attribute of an object (if it is not present it will be created) then the value will be assigned to that attribute.

First case:

You are doing

this.name = name;

So,

p1.set_name('Andrew');

creates a new name attribute in p1 and stores Andrew in it. And when you tried to print p1, the name was looked up on p1 and it was found in p1 itself. So, Andrew was returned. But, when you printed p2, name is not found in p2. It goes up in the hierarchy and finds the name in parent's prototype. So, it returns the empty string.

Second case:

You are doing

this.name['first_name'] = name;

So,

p1.set_name('Andrew');

looks up name in p1. Because you are trying to access 'first_name' on this.name. So, it tries to retrieve name attribute. It doesn't find it in p1, so goes up and finds it in the parent's prototype. It is an empty object and name gets assigned to first_name attribute of that object.

We know that p2's prototype is the same as p1's prototype. We can confirm that like this

console.log(p1.__proto__ === p2.__proto__);
# true

So, when you look up p2's prototype, which is the same as p1's prototype, the name Andrew is found.

Altri suggerimenti

As a general case variables and such are set in the constructor. For more info on the subject and a better explanation than i can do reference here: http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/

// Constructor
function Player() {
    this.names = '';
};

// Public Method
Player.prototype.set_name = function(name){
    this.name = name;
}

// Static method
Player.walk = function() {}

var player1 = new Player();
player1.set_name('John Doe'); // fires the public method
Player.walk(); // fires the static method
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top