why is a.y undefined here?

时间:2015-05-24 20:58:54

标签: javascript inheritance prototype

function A() {}
A.prototype.x = 10;

var a = new A();
alert(a.x); // 10

A.prototype = {
  x: 20,
  y: 30
};

alert(a.y) // undefined
  1. Why does it delegate to old prototype of a.x and not the newer one?
  2. Why is a.y throwing undefined through it is set in prototype?

3 个答案:

答案 0 :(得分:11)

This is happening because of when you've set A.prototype = obj

Rather than adding properties to the Object which is being inherited by a, you've created an entirely new object as A.prototype and this one isn't being inherited by a

Consider,

function A() {}
A.prototype.x = 10;

var p1 = A.prototype; // keep reference to this

var a = new A();

A.prototype = {x: 20, y: 30};

Object.getPrototypeOf(a) === A.prototype; // false, not the new prototype
Object.getPrototypeOf(a) === p1; // true, the old prototype

// however
var b = new A();
Object.getPrototypeOf(b) === A.prototype; // true, this is the new prototype

If you had made the changes to properties on the old prototype (which I called p1) these would have been seen inherited by a

答案 1 :(得分:2)

You just created a new prototype object for the class "A", the old instance of the A

var a = new A();

...did copy the existing prototype object reference for it's instance. That old prototype -object is object of it's own and it is not destroyed because the instance of "A" is holding that reference.

If you want the "y" to be defined, you have to create the object again using new, the new instance would use the object you assinged for the prototype - and that instance has the "y" defined.

http://jsfiddle.net/ejseLum9/

答案 2 :(得分:2)

Why does it delegate to old prototype of a.x and not the newer one? Why is a.y throwing undefined through it is set in prototype?

You have created an entirely new prototype object. objects created already before the prototype property was changed will have the old reference and new objects will have new prototype.

// was before changing of A.prototype
a.[[Prototype]] ----> Prototype <---- A.prototype

// became after
A.prototype ----> New prototype // new objects will have this prototype
a.[[Prototype]] ----> Prototype // it will still reference to old prototype

The thumb rule is, prototype is set the moment of object's creation and later on you cannot change. It is possible only to add new or modify existing properties of the object’s prototype.

However, you can make a workaround with __proto__ property.

function A() {}
A.prototype.x = 10;

var a = new A();
alert(a.x); // 10

var _newPrototype = {
  x: 20,
  y: 30
};
A.prototype = _newPrototype; //will fail
alert(a.y) // undefined

A.__proto__ = _newPrototype; //will work
alert(a.x);
alert(a.y);