`
chengzhi
  • 浏览: 112315 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

extend

阅读更多

extend (Object subclass,Object superclass,[Object overrides] : Object
第一个参数:子类
第二个参数:父类
第三个参数:要覆盖的属性。
这里需要强调一下,子类继承下来的是父类中通过superclass.prototype方式定义的属性(包括用此方法定义的函数)。

使用方式
使用示例
假设有个 function 名为 SuperClass ,要实现一个子类,名为 MyClass 。下面的两种方式都可以实现这个功能。

MyClass = Ext . extend ( SuperClass , { /* */ }); 

Ext . extend ( MyClass , SuperClass , { /* */ }); 

 
 

 

下面来个具体示例:

var a = function ( id ){ 

    this . id = id ; 

} 

a . prototype = { 

    tostring : function (){ 

        return this . id ; 

    } 

}; 

            

b = function ( id ){ 

    b . superclass . constructor . call ( this , id ); 

} 

Ext . extend ( b , a , { 

    tostring : function (){ 

        return String . format ( "b:{0}" , this . id ); 

    } 

}); 

// 测试一下 

var obj1 = new a ( "obj1" ); 

alert ( obj1 . tostring ()); 

var obj2 = new b ( "obj2" ); 

alert ( obj2 . tostring ()); 

 
 

或者下面的代码,可以得到同样的效果:

var a = function ( id ){ 

    this . id = id ; 

} 

a . prototype = { 

    tostring : function (){ 

       return this . id ; 

    } 

}; 

  

b = Ext . extend ( a , { 

    tostring : function (){ 

       return String . format ( "b:{0}" , this . id ); 

    } 

}); 

// 测试一下 

var obj1 = new a ( "obj1" ); 

alert ( obj1 . tostring ()); 

var obj2 = new b ( "obj2" ); 

alert ( obj2 . tostring ()); 

 
 

 

一个错误例子
下面看个示例:

BaseClass = function () { 

    this . f1 = function () { 

        alert ( "f1 in base" ); 

    } 

  

    this . f2 = function () { 

        alert ( "f2 in base" ); 

    } 

} 

  

ChildClass = function () { 

  ChildClass . superclass . constructor . call ( this ); 

}        

  

Ext . extend ( ChildClass , BaseClass , { 

    f1 : function () { 

        alert ( "f1 in child" ); 

    }, 

  

    f3 : function () { 

        alert ( "f3 in child" ); 

    } 

}); 

  

var b = new ChildClass (); 

b . f1 (); 

b . f2 (); 

b . f3 (); 

 
 

 

可以去执行一下,可以发现 f1 的执行结果仍然是 "f1 in base" 。并没有真正的达到 override 的效果。

 

Ext.extend puts the properties specified in the 3rd argument into the subclass's prototype
 

 

也就是说:第三个参数里面的函数被放置在了子类的 prototype 中。

而在 ChildClass.superclass.constructor.call(this); 这句上, BaseClass 的 f1 成了 ChildClass 的变量,而不是 ChildClass.prototype 。通过对 JavaScript 的原型继承的了解,可以知道,实例变量的优先级是高于 prototype 的,所以上面的这个代码是达不到 override 的功能的。

 

修改的方式如下:

BaseClass = function () { 

}; 

  

BaseClass . prototype = { 

    f1 : function () { 

        alert ( "f1 in base" ); 

    } 

}; 

 
 

 

代码解读
JavaScript 中的继承实现
先了解一下最简单的继承是如何实现的:

function Extend ( subFn , superFn ){ 

    subFn . prototype = new superFn () 

    subFn . prototype . constructor = subFn 

} 

  

function Animal (){ 

    this . say1 = function (){ 

        alert ( "Animal" ); 

    } 

} 

  

function Tiger (){ 

    this . say2 = function (){ 

        alert ( "Tiger" ); 

    } 

} 

  

Extend ( Tiger , Animal ); 

  

var tiger = new Tiger (); 

tiger.say1();// "Animal" 

tiger.say2();// "Tiger" 

 
 

 

可以看到最简单的继承只做了两件事情,一是把 subFn 的 prototype 设置为 superFn 的一个实例,然后设置 subFn . prototype . constructor 为 subFn 。

 

Ext.extend 的代码
Ext.extend 函数中用到了 Ext.override ,这个函数把第二个参数中的所有对象复制到第一个对象的 prototype 中。首先贴上 Ext.override 函数的代码:

Ext . override = function ( origclass , overrides ){ 

    if ( overrides ){ 

       var p = origclass . prototype ; 

       for ( var method in overrides ){ 

           p [ method ] = overrides [ method ]; 

       } 

    } 

} 
 

 

 

然后贴上 Ext.extend 的代码:

 

/** 

  * 继承,并由传递的值决定是否覆盖原对象的属性 

  * 返回的对象中也增加了 override() 函数,用于覆盖实例的成员 

  * @param { Object } subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象) 

  * @param { Object } superclass 父类,被继承 

  * @param { Object } overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖 

  * @method extend 

  */ 

function extend (){ 

    // inline overrides 

    var io = function ( o ){ 

       for ( var m in o ){ 

           this [ m ] = o [ m ]; 

       } 

    }; 

    return function ( sb , sp , overrides ){ 

       if ( typeof sp == 'object' ){ 

           overrides = sp ; 

           sp = sb ; 

           sb = function (){ sp . apply ( this , arguments );}; 

       } 

       var F = function (){}, sbp , spp = sp . prototype ; 

       F . prototype = spp ; 

       sbp = sb . prototype = new F (); 

       sbp . constructor = sb ; 

       sb . superclass = spp ; 

       if ( spp . constructor == Object . prototype . constructor ){ 

           spp . constructor = sp ; 

       } 

       sb . override = function ( o ){ 

           Ext . override ( sb , o ); 

       }; 

       sbp . override = io ; 

       Ext . override ( sb , overrides ); 

       return sb ; 

    }; 

}(); 

 
 

 

代码中进行了太多的简写,看起来不是特别方便,把代码中的简写补全,代码如下:

function extend (){ 

    // inline overrides 

    var inlineOverride = function ( o ){ 

        for ( var m in o ) { 

            this [ m ] = o [ m ]; 

        } 

    }; 

    return function ( subFn , superFn , overrides ){ 

        if ( typeof superFn == 'object' ) { 

           // 如果 subFn 也是对象的话(一般来说 subFn 这里放的是父类的构造函数),那么第三个参数 overrides 参数相当于被忽略掉 

            overrides = superFn ; 

            superFn = subFn ; 

           //subFn 重新定义了函数 
            subFn = function (){ 

                superFn . apply ( this , arguments ); 

            }; 

        } 

        var F = function (){ 

        }, subFnPrototype , superFnPrototype = superFn . prototype ; 

        F . prototype = superFnPrototype ; 

         subFnPrototype = subFn . prototype = new F (); 

       subFnPrototype . constructor = subFn ; 

       subFn . superclass = superFnPrototype ; 

        

       if ( superFnPrototype . constructor == Object . prototype . constructor ) { 

            superFnPrototype . constructor = superFn ; 

        } 

        subFn . override = function ( obj ){ 

            Ext . override ( subFn , obj ); 

        }; 

        subFnPrototype . override = inlineOverride ; 

        Ext . override ( subFn , overrides ); 

        return subFn ; 

    }; 

}; 
 

 

 

补全以后也不是特别容易明白,那么我们就把这个代码分开,分为 2 个参数和 3 个参数。

 

两个参数的 Ext.extend 代码
首先把代码改写成两个参数的。

// 两个参数的时候的代码,注意第二个参数必须为 object 

function extend (){ 

    // inline overrides 

    var inlineOverride = function ( o ){ 

        for ( var m in o ) { 

            this [ m ] = o [ m ]; 

        } 

    }; 

    return function ( superFn , overrides ){ 

       var subFn = function (){ 

           superFn . apply ( this , arguments ); 

       }; 

  

        var F = function (){ 

        }, subFnPrototype , superFnPrototype = superFn . prototype ; 

       

        F . prototype = superFnPrototype ; 

       // 注意下面两句就是上面最简单的继承实现。 

        subFnPrototype = subFn . prototype = new F (); 

       subFnPrototype . constructor = subFn ; 

       // 添加了 superclass 属性指向 superFn 的 Prototype 

       subFn . superclass = superFnPrototype ; 

       

       // 为 subFn 和 subFnPrototype 添加 override 函数 

        subFn . override = function ( obj ){ 

            Ext . override ( subFn , obj ); 

        }; 

        subFnPrototype . override = inlineOverride ; 

        

       // 覆盖掉子类 prototype 中的属性 

        Ext . override ( subFn , overrides ); 

        return subFn ; 

    }; 

}; 

  

从注释中可以看到,做的工作很简单,只是定义一个 subFn 函数,这个函数中会调用 superFn 函数。定义了 subFn 以后,就使用上面的最简单的继承方式实现继承。然后为 subFn 和 subFn 的 prototype 添加了一个 override 函数。最后的 Ext.override(subFn, overrides); 把 overrides 中的函数写入 subFn 的 prototype 中。

 

三个参数的 Ext.extend 代码
下面我们把函数改写为只处理 3 个参数的,改写后的代码如下:

// 三个参数时的代码 

function extend (){ 

    // inline overrides 

    var inlineOverride = function ( o ){ 

         for ( var m in o ) { 

            this [ m ] = o [ m ]; 

        } 

    }; 

    return function ( subFn , superFn , overrides ){ 

        var F = function (){ 

        }, subFnPrototype , superFnPrototype = superFn . prototype ; 

       

        F . prototype = superFnPrototype ; 

       // 注意下面两句就是上面最简单的继承实现。 

        subFnPrototype = subFn . prototype = new F (); 

       subFnPrototype . constructor = subFn ; 

       // 添加了 superclass 属性指向 superFn 的 Prototype 

       subFn . superclass = superFnPrototype ; 

  

       // 为 subFn 和 subFnPrototype 添加 override 函数 

        subFn . override = function ( obj ){ 

            Ext . override ( subFn , obj ); 

        }; 

        subFnPrototype . override = inlineOverride ; 

        

       // 覆盖掉子类 prototype 中的属性 

        Ext . override ( subFn , overrides ); 

        return subFn ; 

    }; 

}; 

 

 
 

过程与两个参数的时候相差无几,只是两个参数的时候, subFn 时重新定义的一个 function ,而三个参数的时候,这个步骤就省略了。

总结及说明
这样大家就对这个函数很明白了吧,也可以知道 Ext.extend 的继承只会覆写构造函数 prototype 中的对象,使用的时候需要多加注意。

 

注意下面一段代码:

if ( superFnPrototype . constructor == Object . prototype . constructor ) { 

    superFnPrototype . constructor = superFn ; 

} 

 
 

这段代码我在改写的 Ext.extend 中省略掉了。原因在于我尝试了多次,发现参数为两个参数的时候,只有第一个参数为 Object 对象或者为 3 个参数的时候,第二个参数为 Object 才会进入此段代码。

但是发现 superFn 也时 function Object(){} ,在 IE 和 FF 下都是如此。那么我就不是很清楚这段代码到底是什么用的了,若有清楚的,告诉一声,哈。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/kinglino520/archive/2009/06/24/4294686.aspx

分享到:
评论

相关推荐

    com.guo.android_extend:android-extend:1.0.6

    标题 "com.guo.android_extend:android-extend:1.0.6" 提示我们这是一个 Android 库项目,属于开发者郭某的扩展库,版本号为 1.0.6。通常,这种格式表示的是 Maven 或 Gradle 的依赖坐标,用于在构建 Android 项目时...

    cesium-extend_Extend_cesium拓展entity_cesium_

    "cesium-extend"项目是针对Cesium的功能扩展包,旨在增强其原生能力,提供更多的实用功能,如白模(Wireframe)展示和避让(Occlusion)处理。下面将详细解释这两个关键特性以及如何在Cesium中应用它们。 1. **白模...

    解析UML用例图中include与extend的区别

    解析 UML 用例图中 include 与 extend 的区别 UML 用例图是软件开发过程中的一种重要工具,它能够帮助我们更好地理解和描述业务需求。在 UML 用例图中,有两种重要的关系:include 和 extend。这两种关系都是用来...

    foam-extend-4.1第三方库

    《深入理解foam-extend-4.1第三方库在OpenFOAM中的应用》 OpenFOAM,作为一款开源的计算流体动力学(CFD)软件,被广泛应用于工程和科研领域。它提供了丰富的功能和灵活性,使得用户可以对复杂的流体流动问题进行...

    UML用例图之泛化(generalization)、扩展(extend)和包含(include)关系

    用例的关系有泛化(generalization)、扩展(extend)和包含(include)。其中include和extend最易混淆。下面我们结合实例彻底理清三者的关系。基本概念用例图(UseCaseDiagram):用例图显示谁是相关的用户,用户希望系统...

    com.guo.android_extend android-extend1.0.6.zip

    implementation 'com.guo.android_extend:android-extend:1.0.6'失败,用这个替代就好了 implementation 'com.guo.android_extend:android-extend:1.0.6'失败,用这个替代就好了

    underscore.extend与$.extend实例比较分析

    在JavaScript开发中,`underscore` 和 `jQuery` 都提供了扩展对象的功能,即 `_.extend()` 和 `$.extend()` 方法。这两个方法允许开发者合并一个或多个对象的属性到目标对象中,实现对象间的属性拷贝。本文将深入...

    Adobe Photoshop CS5 Extend 简繁英精简绿色优化版

    Adobe Photoshop CS5 Extend是Adobe公司推出的图像处理软件的高级版本,专为专业摄影师和图形设计师设计,具有丰富的功能和强大的编辑工具。这个“简繁英精简绿色优化版”是针对中国用户定制的一个特别版本,它包含...

    jQuery.extend 函数详解

    ### jQuery.extend 函数详解 #### 一、概述 在JavaScript前端开发中,jQuery是一个非常流行的库,它简化了许多常见的操作,比如DOM操作、事件处理、AJAX交互等。`jQuery.extend`是jQuery提供的一个用于扩展jQuery...

    Extend

    标题“ Extend”可能指的是在编程领域中的扩展或继承概念,这在面向对象编程(OOP)中至关重要。在这个场景下,“ Extend”意味着一个类(子类)从另一个类(父类)继承属性和方法,从而实现代码重用和类的分层结构...

    PS图片出血扩展插件-Image Extend-1.0.0中文汉化版.zip

    "PS图片出血扩展插件-Image Extend-1.0.0中文汉化版.zip"是专为PS设计的一款插件,用于帮助用户轻松实现图片的出血效果处理。出血在印刷术语中是指图像或设计元素超出最终裁切边缘的部分,以避免在裁切后出现白色...

    jquery $.fn.extend

    `$.fn.extend`是jQuery库中的一个核心方法,主要用于扩展jQuery对象的方法集合。这个方法允许开发者自定义jQuery的函数,从而实现对DOM元素的操作或添加新的功能。在jQuery中,`$.fn`实际上是`$.prototype`的一个...

    Java中extend与implement区别.doc

    Java 中 extend 与 implement 的区别 Java 语言中,extend 和 implement 是两个基本概念,它们之间的区别是非常重要的。extend 用于继承类,而 implement 用于实现接口。在 Java 中,不支持多重继承,但是可以使用...

    jquery.validate.extend.js

    jquery.validate.extend.js

    【1积分】android-extend-1.0.6.aar

    使用方式:把资源放到libs下,在gradle app 中添加 低版本:compile files('libs/android-extend-1.0.6.aar') 高版本:implementation files('libs/android-extend-1.0.6.aar')

    生成Code39(extend)条形码源码 GenerateCode39Barcode.rar

    生成Code39(extend)条形码源码 源码描述: 一、源码特点 C#GDI+绘制Code39条形码 。网上开源的众多,但却都是根据内容和长宽来确定模块宽度。本次由于某需求需要根据模块宽度以及数据多少来确定条形码的长宽。识别...

    前端开源库-extend-error

    在前端开发中,错误处理是不可或缺的一部分,而`extend-error`正是一个专为前端和Node.js环境设计的开源库,用于扩展和定义自定义错误类型。这个库使得开发者能够更方便、更规范地管理和报告错误,提高代码的可读性...

Global site tag (gtag.js) - Google Analytics