2011-10-03 34 views
5

Tôi đã luôn luôn giả định rằng nguyên mẫu của một hàm được chia sẻ giữa tất cả các đối tượng, theo nghĩa là tham chiếu. Vì vậy, nếu bạn thay đổi giá trị của một thuộc tính của nguyên mẫu, tất cả các đối tượng chia sẻ mẫu thử nghiệm đó đều có giá trị thay đổi cho chúng. Vì vậy, ví dụ dưới đây có vẻ như là thay vì thanh tài sản được chia sẻ giữa tất cả các đối tượng, nó được sao chép. Thê nay đung không? Các thuộc tính của nguyên mẫu của hàm tạo có được sao chép đơn giản tới tất cả các đối tượng lớp khi chúng được tạo ra hay chúng được chia sẻ bởi liên kết?Javascript và chức năng phân định nguyên mẫu

function foo() 
{ 
    this.bar = 1; 
} 
function derived() { } 
derived.prototype = new foo() 

object1 = new derived() 
object2 = new derived() 

object1.bar = 2; 
//but notice if I had said here derived.prototype.bar = 3, object1.bar would still equal 2 but object2.bar would equal 3 
alert(object2.bar) // this prints 1; 

Trả lời

12

Khi bạn gán object1.bar = 2, bạn đang tạo một tài sản riêng trên object1, khách sạn này chỉ tồn tại trong đó đối tượng dụ, và nó không có gì để làm với nguyên mẫu của nó.

Khách sạn này trên object1 sẽ bóng giá trị của một hiện trên derived.prototype, điều này có nghĩa rằng khi bạn tra cứu object1.bar, nó sẽ tìm thấy một giá trị trực tiếp hiện hành về đối tượng đó.

Ở phía bên kia, nếu bạn tra cứu object2.bar, đối tượng này không có một bar tài sản riêng, do đó tra cứu bất động sản sẽ tìm kiếm trên đối tượng này thừa hưởng từ (derived.prototype) và nó sẽ tìm thấy giá trị 1.

cấu trúc đối tượng của bạn trông giống như sau:

 
object1 
-------- 
| bar: 2 | ----------------- 
--------     |   derived.prototype 
          |  ---------- 
          |------> | bar: 1 | -- foo.prototype 
object2 (no own properties)|  ---------- | ------------------ 
--------     |      -> | constructor: foo | 
|  | -----------------       ------------------ 
--------             | 
                  v 
                ------------------ 
                | Object.prototype | 
                ------------------ 
                  | 
                  v 
                  null 

Trường hợp ---> dòng biểu thị liên kết nội bộ [[Prototype]] thể hiện thừa kế.

+0

ohhh, có ý nghĩa hoàn hảo, miễn là tôi không gán lại nó, nó đề cập đến tài sản thừa kế, vì vậy khi tôi gán nó trở thành tài sản riêng? – rubixibuc

+0

Tôi đã hiểu, rất nhiều, câu trả lời của bạn thật tuyệt vời :-) – rubixibuc

+0

@rubixibuc, phải, khi bạn gán nó, nó sẽ trở thành tài sản riêng và nó sẽ * bóng * mọi giá trị trong chuỗi nguyên mẫu. Cũng lưu ý rằng liên kết '[[Prototype]]' không thể thay đổi khi một đối tượng được tạo ra, ví dụ, sau khi tạo 'object1' và' object2', bạn gán lại một đối tượng khác với 'derived.prototype' sẽ không ảnh hưởng đến các thuộc tính được thừa hưởng bởi hai đối tượng đó. – CMS

2

Ví dụ, bạn có mã:

function Animal() { 
} 
Animal.prototype.name="animal"; 

function Dog() { 
} 
Dog.prototype = new Animal 
Dog.prototype.constructor=Dog; 
Dog.prototype.name="dog"; 

object1 = new Animal(); 
object2 = new Dog(); 

Kết quả là bạn có hai trường hợp đối tượng, trông như (bạn có thể kiểm tra điều này ví dụ như trong Chrome DevTools hoặc FF firebug hoặc ...):

object1: 
    __proto__: (is ref into an Animal.prototype object) 
    constructor: function Animal() 
    name: "animal" 
    __proto__: Object (is ref into an Object.prototype object) 

object2: 
    __proto__: (is ref into an Dog.prototype object) 
    constructor: function Dog() 
    name: "dog" 
    __proto__: (is ref into an Animal.prototype object) 
     constructor: function Animal() 
     name: "animal" 
     __proto__: (is ref into an Object.prototype object) 

Khi bạn chạy mã tiếp theo (ví dụ):

alert(object1.name); // displayed "animal" 
alert(object2.name); // displayed "dog" 

gì đã xảy ra? 1) Javascript tìm kiếm tên thuộc tính trong cá thể đối tượng (trong object1 hoặc object2). 2) Khi không tìm thấy, nó nhìn lên trong đối tượng dụ proto thuộc tính (giống như nguyên mẫu của hàm lớp). 3) Khi không founct nó nhìn trong proto của proto và tiếp theo và tiếp theo trong khi không tìm thấy name bất động sản và những người khác proto tìm thấy. Nếu kết quả của thuộc tính tìm kiếm được tìm thấy, thì giá trị được trả về, nếu không tìm thấy, thì undefined sẽ trả về.

Chuyện gì xảy ra nếu bạn thực thi mã tiếp theo:

object2.name = "doggy"; 

Kết quả là bạn có cho object2:

object2: 
    name: "doggy" 
    __proto__: (is ref into an Dog.prototype object) 
    constructor: function Dog() 
    name: "dog" 
    __proto__: (is ref into an Animal.prototype object) 
     constructor: function Animal() 
     name: "animal" 
     __proto__: (is ref into an Object.prototype object) 

tài sản được phân công trực tiếp vào đối tượng dụ, nhưng đối tượng nguyên mẫu vẫn không thay đổi.Và khi bạn thực hiện:

alert(object1.name); // displayed "animal" 
alert(object2.name); // displayed "doggy" 

Khi bạn cần tạo | thay đổi chia sẻ tài sản của lớp, bạn có thể sử dụng một từ các thuật toán tiếp theo: 1)

Animal.prototype.secondName="aaa"; 
alert(object1.secondName); // displayed "aaa" 
alert(object2.secondName); // displayed "aaa" 
Animal.prototype.secondName="bbb"; 
alert(object1.secondName); // displayed "bbb" 
alert(object2.secondName); // displayed "bbb" 
// but 
Animal.prototype.secondName="ccc"; 
object1.secondName="ddd"; 
alert(object1.secondName); // displayed "ccc" 
alert(object2.secondName); // displayed "ddd" 

2) Tạo thuộc tính kiểu object trong nguyên mẫu của lớp hàm và gán giá trị cho các thuộc tính của đối tượng này.

Animal.prototype.propObject={thirdName:"zzz"}; 
alert(object1.propObject.thirdName); // displayed "zzz" 
alert(object2.propObject.thirdName); // displayed "zzz" 
Animal.prototype.propObject.thirdName="yyy"; 
alert(object1.propObject.thirdName); // displayed "yyy" 
alert(object2.propObject.thirdName); // displayed "yyy" 
object1.propObject.thirdName="xxx"; 
alert(object1.propObject.thirdName); // displayed "xxx" 
alert(object2.propObject.thirdName); // displayed "xxx" 
object2.propObject.thirdName="www"; 
alert(object1.propObject.thirdName); // displayed "www" 
alert(object2.propObject.thirdName); // displayed "www" 
+0

Giải thích rõ ràng. –

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