2013-02-17 27 views
2

快速注意:請不要在您的答案中解釋JavaScript繼承的基礎知識。爲什麼和如何__proto__記得構造函數的未定義原型成員的舊屬性?

這裏是一些簡單的構造函數,它的一些屬性附加到它的原型成員。

function Foo() { 
    this.relationship = "Love"; 
}; 

Foo.prototype.name = "Natalie"; 
Foo.prototype.age = 22; 
Foo.prototype.country = "France"; 

現在我們用Foo創建新對象並測試一些基礎知識。一切都很酷。

var girl = new Foo(); 

girl.hasOwnProperty("relationship"); //=> true 
girl.hasOwnProperty("name");   //=> false 

girl.relationship; //=> "Love" 
girl.name;   //=> "Natalie", this comes from Foo.prototype 

girl.__proto__ === Foo.prototype;   //=> true 
girl.__proto__.name === Foo.prototype.name; //=> true 
girl.name === Foo.prototype.name;   //=> true 

而且,如果我們更新Foo.prototype.name屬性的值,那麼girl.name指向新值,因爲它應該如此。

Foo.prototype.name = "Lucia"; 
girl.name; //=> "Lucia", this comes from Foo.prototype 


神奇的事情發生了,當我們改變Foo.prototype並使其空,未定義,空對象等

Foo.prototype = null; 

如果我們女孩對象有一個隱藏__ proto__(ECMA [原型]])鏈接到Foo.prototype,然後製作Foo.prototype null應該沒有機會女孩獲得名稱財產,但它!

girl.name;  //=> "Lucia" 
girl.age;  //=> 22 
girl.country; //=> "France" 

現在,如果我們在此時使用Foo創建另一個對象。它沒有名稱,年齡國家,因爲,當然,因爲Foo.prototype是空的。

var new_girl = new Foo(); 
new_girl.name;  //=> undefined 
new_girl.age;  //=> undefined 
new_girl.country; //=> undefined 


所以我的問題是如何在地球上以前的對象(女孩)和他的隱藏__ proto__鏈接可以記住這些屬性我們分配Foo.prototype後

回答

2

這並不神祕,它與繼承無關。
它與對象指針/引用有關。

var a = { name : "Bob", age : 32 }; 
var b = a; 

b.name; // "Bob"; 
a.name = "Jim"; 
b.name; // "Jim"; 
a = null; 
b.name; // "Jim"; 

發生了什麼事?

ab被給予指向同一對象的指針。
當您更改對象的屬性時,通過引用其中一個(無論您是在a還是在b上更改它們都沒有關係),其他引用也會看到這些更改。

你不是在創造具有相同屬性和值的新對象,而是給它們兩個同一對象的地址,並且每次詢問它們時都會查找屬性。

然後你重新分配a

你不改變對象,你給a一個地址到其他地方。
b還有地址。

所以,現在想起來是這樣的:

function Foo() { } 
Foo.prototype = { name : "Bob", age : 32 }; 

var a = new Foo(); 
var b = new Foo(); 

a.__proto__ === Foo.prototype; 
b.__proto__ === Foo.prototype; 

Foo.prototype.age = 35; 

a.age; // 35 
b.age; // 35 

// now we're replacing the `.prototype` reference with a brand new object 
Foo.prototype = { name : "Sally", age : 16 }; 

a.__proto__ !== Foo.prototype; 
b.__proto__ !== Foo.prototype; 

a.name; // "Bob" 
b.age; // 35 

所有構造函數是在後臺做的是說:

this.constructor = arguments.callee; 
this.__proto__ = this.constructor.prototype; 

所以,當你改變雙方this.constructor.prototype引用的對象的屬性和this.__proto__上的查找將找到新值。
但從一箇中刪除引用不會刪除另一個的對象。

如果這是你想要的結果,那麼你需要擦除原型的每個屬性(無論你從哪裏進行 - 從函數或任何實例),然後取消.prototype通過將其設置爲一個空對象(null將在較小的瀏覽器上導致錯誤),以便將來的對象無法訪問。

+0

哦,我從一個非常錯誤的角度看它。謝啦。接受的答案。 – 2013-02-17 20:57:44

相關問題