2015-05-24 21 views
10
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. Tại sao nó ủy quyền cho old prototype of a.x và không phải là mới hơn?
  2. Tại sao a.y ném undefined thông qua thiết bị được đặt trong prototype?
+2

Vì 'a' được tạo từ nguyên mẫu cũ. Nó được liên kết với đối tượng nguyên mẫu, không phải là 'A', do đó nhiệm vụ không thay đổi gì cả. Xem thêm [tại đây] (https://stackoverflow.com/questions/14568239/javascriptinstanceof-operator) hoặc [có] (https: // stackoverflow.com/questions/17474390/define-a-javascript-prototype) – Bergi

Trả lời

11

này đang xảy ra vì khi bạn đã thiết A.prototype = obj

Thay vì thêm thuộc tính cho Object đang được thừa hưởng bởi a, bạn đã tạo một đối tượng hoàn toàn mới như A.prototype và cái này không được thừa hưởng bởi a

xem xét,

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 
.210

Nếu bạn đã thực hiện những thay đổi thuộc tính trên nguyên mẫu cũ (mà tôi gọi là p1) những có thể đã được nhìn thấy lần thừa hưởng bởi a

+0

Nó không phải là chúng ta không thể thay đổi ... __proto__ tham khảo nguyên mẫu cũ mà qua đó chúng ta có thể thay đổi nó để tham khảo cái mới hơn. – Thalaivar

+0

@Thalaivar không nên sử dụng 'obj .__ proto__' và rất tốn kém khi sử dụng' Object.setPrototypeOf', nếu bạn đang mong muốn làm những thứ này, hoặc bắt đầu với chuỗi nguyên mẫu dài hơn với trống, bạn có thể sửa đổi hoặc tách mã của bạn để sử dụng nhiều hàm tạo. –

+0

Câu trả lời của bạn là rõ ràng và rõ ràng, nhưng như bạn biết trong JavaScript không có tình trạng bế tắc, luôn luôn có một cách giải quyết mặc dù đôi khi tốn kém như bạn đã đề cập. Chúc mừng :) – Thalaivar

2

Bạn vừa tạo một đối tượng nguyên mẫu mới cho các lớp học "A", dụ cũ của Một

var a = new A(); 

... đã sao chép các đối tượng nguyên mẫu hiện tham khảo cho nó là ví dụ. Đó là nguyên mẫu -object là đối tượng của riêng nó và nó không bị phá hủy bởi vì thể hiện của "A" đang giữ tham chiếu đó.

Nếu bạn muốn "y" được xác định, bạn phải tạo các đối tượng một lần nữa sử dụng mới, các trường hợp mới sẽ sử dụng các đối tượng bạn assinged cho nguyên mẫu - và dụ rằng có "y" được xác định.

http://jsfiddle.net/ejseLum9/

+0

… ngoại trừ nguyên mẫu không được sao chép, chúng được tham chiếu. – Bergi

+1

đúng, đã sửa chữa câu trả lời. –

+0

Cảm ơn! Vâng, chỉ một từ nhỏ bị thiếu :-) – Bergi

2

Tại sao nó đại biểu cho nguyên mẫu cũ của a.x và không phải là một phiên bản mới hơn? Tại sao a.y ném undefined thông qua nó được thiết lập trong nguyên mẫu?

Bạn đã tạo hoàn toàn new prototype object. các đối tượng đã tạo trước khi thuộc tính mẫu thử được thay đổi sẽ có tham chiếu cũ và objects mới sẽ có prototype mới.

// 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 

Nguyên tắc ngón tay cái là, prototype được thiết lập thời điểm sáng tạo của đối tượng và sau này bạn không thể thay đổi. Chỉ có thể thêm mới hoặc sửa đổi các thuộc tính hiện có của object’s prototype.

Tuy nhiên, bạn có thể thực hiện giải pháp thay thế với thuộc tính __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); 
+0

@BlueMoon: Nandri ... – Thalaivar

Các vấn đề liên quan