在JavaScript中,加號是一個多態運算符,它能夠根據傳入值的類型進行不同的計算。從某種意義上來說,多態是面向對像中重要的一部分,也是實施繼承的主要目的。一個實例可以擁有多種類型,既可以是這種類型,也可以是那種類型,這種多類型稱為類的多態。
多態表現為兩個方面:類型的模糊和類型的識別。JavaScript是一種弱類型語言,通過typeof運算符來判斷值的類型,但通過typeof無法確定對象的類型,所有類型的實例對像對於typeof運算符來說都是基本的object,因此JavaScript的類型是比較模糊的。由於沒有嚴格的類型檢測,因此可以為任何對像調用任何方法,無須考慮它是否被設計為擁有該方法。使用JavaScript的原型可以設計類的多態特性。
function A{//超類A
this.get=function{
alert("A");
}
}
function B{//子類B
this.get=function{
alert("B");
}
}
B.prototype=new A;//設置B類繼承A類
function C{//子類C
this.get=function{
alert("C");
}
}
C.prototype=new A;//設置C類繼承A類
function F(x){//多態類F
this.x=x;
}
F.prototype.get=function{
if(this.x instanceof A)//判斷是否為超類的實例,然後調用不同類的方法
this.x.get
}
var b=new B;
var c=new C;
var f1=new F(b);
var f2=new F(c);
f1.get;//B,此時該方法指向的是B類中的方法get
f2.get;//C,此時該方法指向的是C類中的方法get
重載和覆蓋是兩個不同的類型概念,重載(overload)就是指同名方法有多個實現,依靠參數的類型或參數的個數來區分和識別它們。在JavaScript中,函數的參數是沒有類型的,並且參數個數也是任意的。看下面的示例:
function f(x,y){
return x+y;
}
示例中的函數f雖然指定了兩個形參,但是仍然可以在調用時傳遞任意多個實參,參數的類型也可以是任意的。由於JavaScript語言是弱類型語言,不會根據傳遞的參數個數和類型來決定要執行的行為,因此,要定義重載方法,只能夠通過arguments來實現。
function f{
var sum=0;
for(var i=0;i<arguments.length;i++){
if(typeof arguments[i]=="number")
sum+=arguments[i];
}
return sum;
}
上面的函數實現了重載對任意多個參數求和的函數。不管函數f中包含多少個參數,也不管參數類型如何,該函數將會自動把其中的數值類型的參數相加並返回總數。
alert(f(3,4,6,7,8,9));//重載函數f,返回37
alert(f(3,4));//重載函數f,返回7
結合instanceof運算符和constructor屬性來判斷參數類型,並且根據參數個數和類型執行不同的操作,可以實現複雜的方法重載。
覆蓋(overrid)是指在子類中定義的方法與超類中的方法同名,並且參數類型和個數也相同,當子類被實例化後,從超類中繼承的同名方法將被隱藏。下面是一個簡單的示例。
function A{//超類A
this.m=function{
alert("A");
}
}
function B{//子類B
this.m=function{
alert("B");
};
}
B.prototype=new A;//類B繼承類A
B.prototype.constructor=B;//恢復B類的原型對象的構造器
var b=new B;b.m;//字符B,說明子類B的方法m將覆蓋類A的方法m
在強類型語言中,在覆蓋的方法中可以調用被覆蓋的方法(超類的方法),不過可以通過臨時私有變量先保存超類的同名方法,然後在子類同名方法中調用即可。實現的代碼如下:
function A{
this.m=function{
alert("A");
}
}
function B{
var m=this.m;//先使用私有變量保存超類繼承的同名方法
this.m=function{
m.call(this);
alert("B");
};
}
B.prototype=new A;//類B繼承類A
B.prototype.constructor=B;
var b=new B;
b.m;//字符B,說明子類B的方法m將覆蓋類A的方法m
在覆蓋方法中調用超類的同名方法時,需要使用call或apply方法來改變執行上下文為this,如果直接調用該方法,執行上下文就會變成全局對象,在特殊語境中可能會發生歧義。