JavaScript物件導向編程(4)重寫prototype造成的混亂
先來看兩個現象:
1.分量形式聲明prototype(部分重寫),prototype的構造器為宿主函數而不是Object,就像直接給宿主構造器增加了屬性一樣
function Dog(){this.tail = true;}//建立兩條狗,注意此時還沒有定義prototypevar benji = new Dog();var rusty = new Dog();Dog.prototype.say = function(){return 'Woof!';}//1.部分重寫,prototype的構造器為宿主函數而不是Object,就像直接給宿主構造器增加了屬性一樣alert(部分重寫,其構造器:+benji.constructor.prototype.constructor);//正式因為這個特性,在prototype定義之前建立的對象,仍自動獲得了prototype的屬性alert(benji.say()===+benji.say());//正常,可用
2.第二個現象是,如果將prototype直接定義為一個簡單對象,這個動作叫做完全重寫
這時prototype的構造器為Object,宿主構造器不直接具備prototype的屬性
也正式因為如此,在prototype聲明之前已經建立好的對象,不能使用prototype的屬性
——完全重寫將原來的執行個體和prototype切斷了
//用完全重寫形式Dog.prototype = {paws: 4,hair: true};alert(完全重寫,其構造器===+benji.constructor.prototype.constructor);/*在prototype聲明之前已經建立好的對象,不能使用prototype的屬性,完全重寫將原來的執行個體和prototype切斷了*/alert(benji.say()===+benji.say());//正常alert(用之前對象訪問prototype對象的屬性::+benji.paws);//undefined
所以,你首先必須記住,部分重寫就像直接給宿主構造器增加了屬性一樣,而完全重寫則不是。由此引發了舊對象訪問新屬效能不能訪問的區別。
3.完全重寫後建立的對象上只具備原始屬性和完全重寫中定義的屬性
完全重寫之前建立的對象上則具備原始屬性和之前的部分重寫屬性
//用完全重寫形式Dog.prototype = {p1: 888,p2: 999};var lucy = new Dog();//建立對象for(i in lucy){alert(i);//tail p1 p2}for (i in benji) {alert(i);//tail say}
4.上面的內容還是比較好理解,
部分重寫的屬性(或方法),重寫後新老對象都可以用,完全重寫的屬性(或方法)只有新對象才能用,完全重寫還會屏蔽掉以前的prototype屬性;
另外還有一個問題,會造成困擾,就是完全重寫後的構造器指標錯誤:
Dog.prototype = {p1: 888,p2: 999};var lucy = new Dog();//建立對象/*4.完全重寫後的構造器指標錯誤*/alert(lucy.constructor);//Object?
如何修正呢?只需重設下prototype的constructor指向即可:
Dog.prototype = {p1: 888,p2: 999};Dog.prototype.constructor = Dog; var lucy = new Dog();//建立對象/*重設構造器指標後,正常了*/alert(lucy.constructor);
這部分內容主要是為“繼承”做準備,大家知道繼承、封裝、多態是物件導向的特徵,所以不得不瞭解js中的繼承。