標籤:
接上一節的建立對象的模式:
原型模式:
對於prototype的理解:我們建立的函數都有一個prototype(原型)屬性,這個屬性是一個指標指向一個對象,而這個對象的用途是包含基於這個方法的
所有的執行個體的共用屬性和方法。並且每個原型對象都會預設的自動擷取一個constructor(建構函式)的屬性。這個屬性包含一個執行這個prototype屬性所在函數的指標。
function Person(){}Person.prototype.name = ‘kim‘;Person.prototype.age = 10;Person.prototype.sayName = function(){ alert(this.name);};var person1 = new Person();person1.sayName();var person2 = new Person();person2.sayName();
當我們在執行個體中定義一個和prototype中已有屬性重名的屬性的時候,該屬性會屏蔽掉prototype中的這個屬性。而不會修改prototype中的這個屬性。
person1.name = ‘tom‘;
alert(person1.name);//tom而不是kim
如果我們在這種情況下依然放問到prototype中的屬性,我們可以使用delete操作符來刪除執行個體中的這個屬性。
檢測屬性在執行個體中還是原型中的方法有:person2.hasOwnPrototype(‘name‘);//false只會在當屬性是在執行個體中定義了才會返回true。
in:操作符:無論屬性是在prototype還是執行個體中,只要這個執行個體具有這個屬性就會返回true;
alert(‘name‘ in person2);//true
person2.name = ‘jimmie‘;
alert(‘name‘ in person2);//true
delete person2.name;
alert(‘name‘ in person2);//true
---------綜合上面的兩種方法就可以確定一個屬性到底是在執行個體中還是原型中
function hasPrototypeProperty(object, name){
return !object.hasOwnPrototype(name) &&(name in object);//true-->在原型中;false-->在執行個體中
}
Object.keys(對象執行個體);返回可枚舉的屬性Object.getOwnPrototypeNames(Person.prototype);//屬性不論是否可枚舉都會返回。這兩個方法都可以替代
for-in來確定屬性是否可以被執行個體方法到。
我們每次在用執行個體訪問屬性的時候都會逐個在執行個體和prototype中尋找這個屬性,訪問順序是先在執行個體中尋找指定的屬性如果找到就會直接返回(所以當執行個體中
定義了和prototype中相同的屬性和方法的時候,執行個體中的屬性就會阻斷與prototype中屬性的訪問)然後才逐個訪問prototype中的屬性(所以當我們在prototype
中更新了或者建立了一個屬性,當執行個體訪問時就可以立即放問到) 但是當我們重寫了這個執行個體的原型就會出現意想不到的結果:
function Person(){}var person1 = new Person();Person.prototype={ name: ‘tom‘, sayName: function(){ alert(this.name); }};person1.sayName();//出現錯誤
當我們調用建構函式初始化一個執行個體的時候,會自動的產生一個指標([[Prototype]]),而這個指標指向的最初的原型,而後來我們把原型對象徹底重寫以後,就相當於
切斷了建構函式與最初原型之間的聯絡。所以必須要記住:執行個體中的指標指向的是原型對象,而不是建構函式
原型模式最主要的缺點:建立的所有的屬性和方法都是所有執行個體所共用的。所以當我們需要一些每個執行個體都具有的特定的屬性和方法的時候,原型模式就不是太合適了。
javascript 進階程式設計 十一