xieex's blog


从事软件开发的交流平台

我的人生信念:态度决定一切
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

JavaScript拷贝继承法的应用

Posted on 2008-11-14 21:44  xieex  阅读(2030)  评论(5编辑  收藏  举报

前面在JavaScript中继承的实现方法 讲了JavaScript中继承的几种实现方法,这段时间正好在看AJS框架,该框架中用到的是“拷贝继承法”,于是自己仿照写了一个简单的“拷贝继承法”的框架,并加了一些具体的注释,但是有的地方不知道怎样去描述,觉得有不妥的地方,待理解更加透彻之后再修改。

附上源代码:

 

    <script language="JavaScript">

    
//拷贝继承法的使用
    //引擎类EngineClass的作用是完成继承操作
    //父类ParentClass是引擎类EngineClass的对象
    //子类ChildClass是调用ParentClass.extend返回的对象。其实,ChildClass就是继承ParentClass的子类



    
//定义引擎类EngineClass
    EngineClass = function(members)
    
{
        
var fn = function()   
        
{
          
if(arguments[0!= 'no_init')    //如果没有必须执行的方法,该函数体可以为空。
          {
             
return this.NeedInit.apply(this, arguments);   //初始化类中必须有NeedInit方法
             //构造函数 改变this.NeedInit函数中的this指针(即函数内部的this)。执行继承该类的this.NeedInit函数
          }

        }

        fn.prototype 
= members;   //将参数中的方法赋给prototype,创建类对象后,就可以用对象来调用相应的方法
        for(var i in EngineClass.prototype)   //将EngineClass的prototype属性赋给类对象
            fn[i] = EngineClass.prototype[i];
        
return fn;
    }


    EngineClass.prototype 
= 
    
{
        extend: 
function(members)   //拷贝继承法  扩展members成员,然后传入到EngineClass类构造函数,返回EngineClass对象
        {
           
var parentmembers = new this('no_init');  
           
//调用构造函数 即EngineClass中的fn() 返回parentClass对象中方法列表对象

           
for(k in members)     //将父类和子类的方法都合并起来,并且形成继承关系
           {
              
var prev = parentmembers[k];  //父类的方法
              var cur = members[k];         //子类的方法
              if (prev && prev != cur && typeof cur == 'function'
              
{
                 cur 
= this.__parentize(cur, prev); 
                 
//如果父类对象中有该方法,则更改子方法中的this指针,让子类中的方法可以调用父类的同名方法
              }

              parentmembers[k] 
= cur; //将子类中的方法加入到父类对象中来(同名则覆盖)
           }

           
return new EngineClass(parentmembers);  //返回类对象(父类和子类的方法都合并起来)
        }
,

        __parentize: 
function(cur, prev) //指定父类同名方法 
        {
           
return function()
           
{
              
this.parent = prev;     //在子类中调用this.parent({});就可以调用父类的同名方法了。
              return cur.apply(this, arguments);  
              
//this代表EngineClass对象(加了parent)这样子类中的方法就调用父类的同名方法了
           }

        }
,

        init: 
function()
        
{
           alert(
'初始化EngineClass后就可以调用我');
        }

    }



    
//创建基类EngineClass的对象ParentClass(ParentClass对象可以调用extend,init方法) ParentClass相当于基类  
    //将{init,func2,func3}作为参数赋给EngineClass构造函数的members
    ParentClass = new EngineClass
    (
      
{
         NeedInit: 
function()
         
{
            alert(
'ParentClass父类,该方法必须存在! 我有子类来调用');
         }
,
         ParentClassinit: 
function()
         
{
            alert(
'1、EngineClass做拷贝继承操作 2、必须对象化ChildClass类  才能调用ParentClassinit');
         }

      }

    )


    
//ChildClass将返回ParentClass.extend方法中的返回的对象,如果该方法中为空,则表示返回undefined
    //所以要要求EngineClass类的extend方法要做一些拷贝方法的操作,来完成继承操作  ChildClass相当于继承ParentClass的子类
    //调用extend方法,将{func1,func2,func3}作为参数赋给members
    ChildClass = ParentClass.extend  
    (
       
{
            NeedInit: 
function()  //创建对象时就调用了。
         {
            alert(
'ChildClass子类,该方法必须存在!创建对象时就调用了,类似构造函数');
            
this.parent({});//调用父类的NeedInit方法
         }
,
         ChildClassinit: 
function()
         
{
            alert(
'1、EngineClass做拷贝继承操作 2、必须对象化ChildClass类  才能调用ChildClassinit');
         }

       }

    )
       

    
var current = new ChildClass();
    current.ChildClassinit();  
//类的prototype方法,必须初始化对象后才能调用
    current.ParentClassinit();  //类的prototype方法,必须初始化对象后才能调用

    ParentClass.init();  
//不是类的prototype方法,不必初始化对象,可以直接调用
    ChildClass.init();    

    
</script>