一般原型继承的写法 xxx.prototype = new Base();,但是new Base 这样的写法怎么能对构造器传入参数呢?明显写死了而不能传入参数——必然要有其他的做法。什么做法?我们很容易想到 sub.prototype = base.prototype,但这样直接的写法虽然看上去可以,实际上却很危险,因为这相当于设置同一个原型链(Prototype Chain)——在同一个类上修改 protoype 成员,原型链上一旦出现变动,就会影响了继承链,结果便是“子类修改了父类的行为”,让其他同级的子类也牵连进来——这万万不是我们想见到的情况,不可采用。于是再加权衡,想到了通过一个中介“类”Dummy Function 的方法,也就是 Douglas Crockford 给出的、曾经十分推崇的 Obejct.creat() 方法,——即可解决同一继承链种种不足所带来的问题。这正是 D.C 为何在他的文章中如此推崇Obejct.creat()方法的原因。本文篇幅所限,就不详细说个中原理了,都在 D.C 文章早有全面介绍。
继承的方法我定义在 Object.extend() 中,详细源码如下:
- // @parma {Function} base 父类
- // @parma {Function} sub 子类
- Object.extend = function(base, sub){
- var dummy = function(){}
- dummy.prototype = base.prototype; // key step!
- var superObject = new dummy;
- var subProto = sub.prototype;
- sub.prototype = superObject;
- sub.prototype.constructor = base;
- for(var i in subProto){
- if(i in sub.prototype){
- sub.prototype["_" + i] = sub.prototype[i]; // 规定_开头为父类成员
- sub.prototype[i] = subProto[i];
- }else{
- sub.prototype[i] = subProto[i];
- }
- }
- return sub;
- }
测试代码如下(在winxp sp3/IE6上通过):
- function base(a1, a2){
- this.a1 = "init...base class, the value is " + a1;
- this.a2 = a2;
- }
- base.prototype = {
- sayHi:function (){
- this.sayingHi = true;
- return "Hello";
- }
- };
- function sub(a3, a4){
- //base.apply(this, [1]);
- this.a2 = 2;
- this.a3 = 'init...sub class, the value is ' + a3;
- this.a4 = a4;
- }
- sub.prototype.sayHi = function(){
- var hi = base.prototype.sayHi.call(this) + " World"
- return hi;
- }
- sub.print = function(_instance){
- return _instance.saiHi();
- }
- function sub2(){}
- sub2.prototype.sayHi = function(){
- return this._sayHi() + ' Man!';
- }
- _extend(base, sub);
- _extend(sub, sub2);
- foo = new sub2;
- alert(foo.sayHi());
- lert(foo instanceof base);
另外,还根据上述继承的思路炮制了一个 Obejct.mix() 多态应用。所谓的多态,于此表现得也比较简单了,说穿了仍然是常见的“复制成员到某地”。
- // @parma {Function} class 父类
- // @parma {Function} mix 多态类
- Object.mix = function(_class, mix){
- var
- classProto = _class.prototype
- ,mixProto = mix.prototype;
- for(var i in mixProto){
- if(i in classProto){
- classProto["_" + i] = mixProto[i];
- }else{
- classProto[i] = mixProto[i];
- }
- }
- }
以上几点算不上思路,偶有所得,大家来谈谈亦无妨。