在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,如果直接调用该方法,执行上下文就会变成全局对象,在特殊语境中可能会发生歧义。