用JavaScript實現單繼承和多繼承的簡單方法

JavaScript是一種強大的多泛型編程語言,其融合了面向過程、面向對象和函數式編程於一身,具備強大的表現能力。


JavaScript就其本質是函數式編程語言,是Lisp的後代,同時又加入了一下面向對象編程的元素,放棄了一些難懂的函數式語言的元素。 

函數式編程語言可以實現面向對象編程,這是毫無疑義的,Curry方法可以實現對類和對象的模擬。但是JavaScript提供了另一種實現OOP的方法:原型繼承。 

因此,JavaScript實現面向對象編程和一般的函數式編程語言還是有所區別的。 

本文我將會給大家介紹JavaScript實現單繼承和多繼承的方法。 

用原型實現單繼承: 
有很多JavaScript庫提供了一些函數幫助實現單繼承。但實際上,JavaScript本身就提供了原型繼承的方法。因此,根本不需要提供特定的方法來實現,簡單使用JavaScript代碼就可以實現單繼承。

但是,JavaScript提供的原型繼承方法很容易犯錯,下面我給大家演示一下怎樣簡潔明瞭地實現原型繼承。 

假設MyB繼承MyA類,那麼,代碼如下: 

function MyA(){ 

if(MyA.prototype.baseClass!==undefined){ 

MyA.prototype.baseClass.call(this); 



……一般代碼 





function MyB(){ 

if(MyB.prototype.baseClass!==undefined){ 

MyB.prototype.baseClass.call(this); 



……一般代碼 



MyB.prototype=new MyA(); 

MyB.prototype.baseClass=MyB.prototype.constructor;//使用baseClass引用//基類的構造器函數。 

MyB.prototype.constructor=MyB;//恢復子類的構造器屬性 用於未來通過這個屬性判//斷對象的類型。 

var myA=new MyA(); 



var myB=new MyB(); 



上述javascript代碼中,我在每一個構造函數中都添加了這麼一段代碼: 

if(ClassName.prototype.baseClass!==undefined){ 

ClassName.prototype.baseClass.call(this); 



這段代碼尋找原型中的baseClass方法,如果有,就調用它。 

在後面的原型繼承的實現中,我爲子類創建了baseClass屬性,它的值是基類的構造函數。因此,只要遵守我的方式編寫代碼,就可以保證基類的構造函數在子類構造實例時會得到執行。 

現在,如果MyA類又繼承了Base類,只需要添加3行原型繼承代碼即可: 

MyA.prototype=new Base(); 

MyA.prototype.baseClass= MyA.prototype.constructor;//使用baseClass引用//基類的構造器函數。 

MyA.prototype.constructor= MyA;//恢復子類的構造器屬性 用於未來通過這個屬性判//斷對象的類型。 


不需要修改MyA類本身的代碼,MyA類及其子類MyB類的實例就都可以得到正確的執行。 

那些JavaScript庫實現的繼承,需要修改Object,Function等基類,容易引起衝突。還有一些方法,每一次實現繼承,都必須手工修改子類的構造函數,以使構造函數能夠正確調用基類的構造函數。 


上面提供的方法編寫JavaScript代碼很好地解決了這些問題。 

用Mixin(混入)實現多繼承 
JavaScript本身並沒有提供多繼承的機制,但我們可以使用Mixin(混入)這種技巧實現多繼承的效果。 

下面是我編寫的Mixin助手方法,可以爲類和對象動態添加屬性。 

1,copyClassPrototypeProperties複製類的原型屬性 
/** 

* 把源類原型上的所有屬性複製到目標對象上,第一個參數是boolean值,表示是否覆蓋目標類的原型的屬性 



*/ 

function copyClassPrototypeProperties(isOverride,receivingClass,givingClass){ 

if(arguments.length>3){ 

for(var i=3;i<arguments.length;i++){ 

receivingClass.prototype[arguments[i]]=givingClass.prototype[arguments[i]]; 



}else if(arguments.length==3){ 

for(var name in givingClass.prototype){ 

if(isOverride){ 

receivingClass.prototype[name]=givingClass.prototype[name]; 



}else{ 

//不覆蓋 

if(!receivingClass.prototype[name]){ 

receivingClass.prototype[name]=givingClass.prototype[name]; 






}else{ 

throw "Please give 3 arguments at least!"; 




2,copyObjectProperties複製對象的屬性 
/* 

* 把源對象的所有屬性複製到目標對象上,第一個參數是boolean值,表示是否覆蓋目標對象的屬性 

*/ 

function copyObjectProperties(isOverride,receivingObject,givingObject){ 

if(arguments.length>3){ 

for(var i=3;i<arguments.length;i++){ 

receivingObject[arguments[i]]=givingObject[arguments[i]]; 



}else if(arguments.length==3){ 

for(var name in givingObject){ 

if(isOverride){ 

receivingObject[name]=givingObject[name]; 



}else{ 

//不覆蓋 

if(!receivingObject[name]){ 

receivingObject[name]=givingObject[name]; 






}else{ 

throw "Please give 3 arguments at least!"; 



3,copyProperties複製屬性到對象 
/* 

* 把屬性複製到目標對象中,屬性可以有任意多個,並且可以是數組。 



*/ 

function copyProperties(target){ 

for (var i=1;i<arguments.length;i++){ 

if(arguments[i].constructor===Array){ 

copyArrayProperties(target,arguments[i]); 

}else{ 

for(var name in arguments[i]){ 

target[name] =arguments[i][name]; 





/* 

* 把數組格式的屬性複製到目標對象中,用戶不應該直接調用這個方法 

*/ 

function copyArrayProperties(target,arrayArg){ 

for(var i=0;i<arrayArg.length;i++){ 
if(arrayArg[i].constructor===Array){ 
copyArrayProperties(target,arrayArg[i]); 

}else{ 
for(var name in arrayArg[i]){ 
target[name] =arrayArg[i][name]; 




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章