简洁明了地用JavaScript实现单继承和多继承

来源:互联网 发布:java ipad微信 编辑:程序博客网 时间:2024/05/16 02:52

  JavaScript是一种强大的多泛型编程语言,其融合了面向过程、面向对象和函数式编程于一身,具备强大的表现能力。

         JavaScript就其本质是函数式编程语言,是Lisp的后代,同时又加入了一下面向对象编程的元素,放弃了一些难懂的函数式语言的元素。

         函数式编程语言可以实现面向对象编程,这是毫无疑义的,Curry方法可以实现对类和对象的模拟。但是JavaScript提供了另一种实现OOP的方法:原型继承。

         因此,JavaScript实现面向对象编程和一般的函数式编程语言还是有所区别的。

         本文我将会给大家介绍JavaScript实现单继承和多继承的方法。

用原型实现单继承:

         有很多JavaScript库提供了一些函数帮助实现单继承。但实际上,JavaScript本身就提供了原型继承的方法。因此,根本不需要提供特定的方法来实现,简单使用JavaScript代码就可以实现单继承。

 

         但是,JavaScript提供的原型继承方法很容易犯错,下面我给大家演示一下怎样简洁明了地实现原型继承。

         假设MyB继承MyA类,那么,代码如下:

function MyA(){

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

       MyA.prototype.baseClass.apply(this,arguments);

    }

   ……一般代码

}

 

function MyB(){

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

       MyB.prototype.baseClass.apply(this,arguments);

    }

    ……一般代码

}

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.apply(this,arguments);

    }

    这段代码寻找原型中的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助手方法,可以为类和对象动态添加属性。

1copyClassPrototypeProperties复制类的原型属性

/**

 * 把源类原型上的所有属性复制到目标对象上,第一个参数是boolean值,表示是否覆盖目标类的原型的属性

 

 */

functioncopyClassPrototypeProperties(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 "Pleasegive  3 arguments at least!";

      

    }

   

}

2copyObjectProperties复制对象的属性

/*

 * 把源对象的所有属性复制到目标对象上,第一个参数是boolean值,表示是否覆盖目标对象的属性

 */

functioncopyObjectProperties(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 "Pleasegive  3 arguments at least!";

      

    }

   

}

3copyProperties复制属性到对象

/*

 * 把属性复制到目标对象中,属性可以有任意多个,并且可以是数组。

 

 */

 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];

             }

          }

       

        }

 

 }

 

 

原创粉丝点击