Почему здесь a.y undefined?

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

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

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

alert(a.y) // undefined
  • Почему он делегирует old prototype of a.x, а не новее один?
  • Почему a.y выбрасывание undefined через него устанавливается в prototype?

Ответ 1

Это происходит из-за того, что вы установили A.prototype = obj

Вместо добавления свойств к объекту, который наследуется a, вы создали совершенно новый объект как A.prototype, и этот не наследуется a

Рассмотрим,

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

Если вы внесли изменения в свойства старого прототипа (который я назвал p1), они были бы унаследованы a

Ответ 2

Вы только что создали новый объект-прототип для класса "A", старый экземпляр A

var a = new A();

... скопировал существующий объект прототипа reference для экземпляра. Этот старый прототип -объект является его собственным объектом и не уничтожается, потому что экземпляр "A" содержит эту ссылку.

Если вы хотите определить "y", вам нужно снова создать объект , используя новый, новый экземпляр будет использовать объект, который вы запросили для прототипа, - и этот экземпляр имеет "y".

http://jsfiddle.net/ejseLum9/

Ответ 3

Почему он делегирует старый прототип a.x, а не новый? Почему a.y бросает undefined через него, установленный в прототипе?

Вы создали полностью new prototype object. объекты, созданные уже до изменения свойства прототипа, будут иметь старую ссылку, а новый objects будет иметь новый 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

Правило большого пальца, prototype задается момент создания объекта, а затем вы не можете изменить. Можно добавлять только новые или изменять существующие свойства object’s prototype.

Однако вы можете сделать обходной путь с помощью свойства __proto__.

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);