无参数类继承的问题
先看一段示例代码,实现b继承于a:
复制代码 代码如下:
function a() {
}
a.prototype.a1 = function() {
};
function b() {
}
b.prototype = new a();
b.prototype.b1 = function() {
};
var b = new b();
alert(b.constructor == a); // true
alert(b.constructor == b); // false
这段代码的主要问题是:
* 需要实例化a作为b的原型,此时就执行了a的构造函数。但按照面向对象的规则,实例化b之前,b及其父类a的构造函数都不应该执行。
* 更改了b的prototype,导致b.constructor不是b而是a。
有参类继承的问题
假设a和b都有两个字符串参数s1和s2,a中计算了两段字符串的总长度,b直接以s1、s2为参数调用a:
复制代码 代码如下:
function a(s1, s2) {
this.totallength = s1.length + s2.length;
}
a.prototype.a1 = function() {
};
function b(s1, s2) {
}
b.prototype = new a();
b.prototype.b1 = function() {
};
new b(ab, 123);
可以看到,这段代码中根本没有办法把s1和s2传到a,而又因为实例化a作为b的原型时没有参数,所以出现了异常:
复制代码 代码如下:
s1 is undefined
解决方案
s1和s2的作用域只在b内,要把它们传到a,就只能在b中操作,借助函数的apply方法就可以实现之:
复制代码 代码如下:
function b(s1, s2) {
a.apply(this, arguments);
alert(this.totallength);
}
接下来的问题就是如何把a的方法添加到b的原型中去。这也不难,只要遍历a.prototype,把方法复制到b.prototype即可。要注意的是,对于同名的方法,自然是子类优先(重载),因而不能覆盖:
复制代码 代码如下:
for (var m in a.prototype) {
if (!b.prototype[m]) { // 父类不能覆盖子类的方法
b.prototype[m] = a.prototype[m];
}
}
后记
考虑到c#、java等高级语言都抛弃了多继承,因此,本文所讨论的也只是单继承的情况。而本文所述的继承方法,也会写成jraiser的一个扩展,迟些发布。