最近學了 JS 的面向對象,這篇文章主要是探討 JS 的面向對象中繼承的那些事。 JS中繼承的特點: 1、子類繼承父類; 2、子類可以用父類的方法和屬性 3、子類的改變可以不影響父類 下麵用一個例子來說明 JS 的繼承 這段代碼創建了一個父類以及它的原型,同時還創建了一個子類,並繼承了父類的私有屬性 ...
最近學了 JS 的面向對象,這篇文章主要是探討 JS 的面向對象中繼承的那些事。
JS中繼承的特點:
1、子類繼承父類;
2、子類可以用父類的方法和屬性
3、子類的改變可以不影響父類
下麵用一個例子來說明 JS 的繼承
這段代碼創建了一個父類以及它的原型,同時還創建了一個子類,並繼承了父類的私有屬性
1 <script> 2 //這是父類 3 function Father(name,age,marry){ 4 this.name=name; 5 this.age=age; 6 this.marry=marry; 7 } 8 //父類的原型 9 Father.prototype.showName=function(){ 10 alert(this.name); 11 } 12 13 //子類 14 function Son(name,age,marry,weight){ 15 Father.call(this,name,age,marry); 16 this.weight=weight; 17 } 18 19 </script>
當子類Son想繼承父類的原型時,我的做法一開始是這麼做的
1 <script> 2 //這是父類 3 function Father(name,age,marry){ 4 this.name=name; 5 this.age=age; 6 this.marry=marry; 7 } 8 //父類的原型 9 Father.prototype.showName=function(){ 10 alert(this.name); 11 } 12 13 //子類 14 function Son(name,age,marry,weight){ 15 Father.call(this,name,age,marry); 16 this.weight=weight; 17 } 18 19 //錯誤的做法 20 Son.prototype=Father.prototype; 21 Son.prototype.showAge=function(){ 22 alert(this.age); 23 } 24 var father=new Father('王大錘',30,true); 25 alert(father.showAge); 26 27 </script>
運行的結果可以發現,子類原型的改變影響了父類的原型,父類的原型中本來是沒有showAge方法的,這就違背了前面繼承的第三個特點了。
分析原因:上面代碼的第20行 Son.prototype=Father.prototype;這裡的 '=' 兩邊都是對象,那麼它代表的意思就是引用,如果是引用的話,左邊的對象改變,肯定會影響了右邊的對象
所以才出現了子類原型的改變影響了父類的原型。
解決辦法
方法一:核心思路,前面的問題不是說 '=' 是引用的關係才導致問題的嘛,那這裡就保證 '=' 永遠是賦值的關係,而不是引用。這裡就定義一個 Clone() 方法,將父類對象拷貝給子類。
Clone() 方法里用到遞歸的原因是,在拷貝的過程中對象中可能嵌套對象。
1 <script> 2 //這是父類 3 function Father(name,age,marry){ 4 this.name=name; 5 this.age=age; 6 this.marry=marry; 7 } 8 //父類的原型 9 Father.prototype.showName=function(){ 10 alert(this.name); 11 } 12 13 //子類 14 function Son(name,age,marry,weight){ 15 Father.call(this,name,age,marry); 16 this.weight=weight; 17 } 18 Son.prototype=new Clone(Father.prototype); 19 Son.prototype.showAge=function(){ 20 alert(this.age); 21 } 22 var father=new Father('王大錘',30,true); 23 alert(father.showAge); 24 25 //通過克隆對象:核心思路是保證 '=' 是賦值的關係,而不是引用,也就是保證 '=' 的右邊不是對象 26 function Clone(obj){ 27 for(var i=0;i<obj.length;i++){ 28 if(typeof(obj[key]=='object')){ 29 this.key=new Clone(obj[key]); 30 }else{ 31 this.key=obj[key]; 32 } 33 } 34 } 35 </script>
這時候的結果父類對象的showAge方法是undefined
方法二:代碼很簡單,但是很難想到,沒有第一個方法那麼好理解。核心思想:對象自身屬性的改變,不會影響其構造函數的屬性的改變。
1 <script> 2 //這是父類 3 function Father(name,age,marry){ 4 this.name=name; 5 this.age=age; 6 this.marry=marry; 7 } 8 //父類的原型 9 Father.prototype.showName=function(){ 10 alert(this.name); 11 } 12 13 //子類 14 function Son(name,age,marry,weight){ 15 Father.call(this,name,age,marry); 16 this.weight=weight; 17 } 18 function fn(){} 19 fn.prototype=Father.prototype; 20 Son.prototype=new fn(); 21 Son.prototype.showAge=function(){ 22 alert(this.age); 23 } 24 var father=new Father('王大錘',30,true); 25 alert(father.showAge); 26 27 //通過克隆對象:核心思路是保證 '=' 是賦值的關係,而不是引用,也就是保證 '=' 的右邊不是對象 28 // Son.prototype=new Clone(Father.prototype); 29 // function Clone(obj){ 30 // for(var i=0;i<obj.length;i++){ 31 // if(typeof(obj[key]=='object')){ 32 // this.key=new Clone(obj[key]); 33 // }else{ 34 // this.key=obj[key]; 35 // } 36 // } 37 // } 38 </script>