Ext.extend 用法以及代码解读
2010-03-11 16:37
295 查看
概述
Ext.extend是
Ext
的继承机制,这个函数的代码相当难懂。要明白这个函数的代码,首先要知道这个函数如何使用。
使用方式
使用示例
假设有个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
下都是如此。那么我就不是很清楚这段代码
到底是什么用的了,若有清楚的,告诉一声,哈。
上面的有几段代码源自网络,若有版权侵犯,非常抱歉。
From : http://www.blogjava.net/dragonshrimp/archive/2008/03/01/183060.html
相关文章推荐
- Ext.extend用法以及代码解读
- Ext.extend用法以及代码解读
- Ext.extend用法以及代码解读
- 一个WinForm记事本程序(包含主/下拉/弹出菜单/打开文件/保存文件/打印/页面设置/字体/颜色对话框/剪切版操作等等控件用法以及记事本菜单事件/按键事件的具体代码)
- 对于Ext.data.Store 介紹 与总结,以及对以前代码的重构与优化
- 离散傅里叶变换代码解读以及一些展示,by《opencv3编程入门》p139
- Extjs Ext.ux.IFrame的用法 以及父子窗口间函数相互调用
- 一个WinForm记事本程序(包含主/下拉/弹出菜单/打开文件/保存文件/打印/页面设置/字体/颜色对话框/剪切版操作等等控件用法以及记事本菜单事件/按键事件的具体代码)
- 一个WinForm记事本程序(包含主/下拉/弹出菜单/打开文件/保存文件/打印/页面设置/字体/颜色对话框/剪切版操作等等控件用法以及记事本菜单事件/按键事件的具体代码)
- JS代码中!!的用法,以及代码性能对比
- 【Unity&JSON&XML】存档数据代码解读&NET.JSON的用法探究
- jquery中事件委派代码分析以及jQuery中delegate和on的用法与区别详细解析
- AngularJS extend用法详解及实例代码
- selinux在android中用法以及内核中代码实现
- [代码安全] 关于全局变量被修改以及volatile的用法
- ExtJs实践(1)——Ext.extend的用法
- 问题:下载页面代码? 以及php中header的用法。
- JSON简介以及用法代码汇总
- 转载 Ext.extend用法(ext的继承)
- 代码添加约束以及第三方库的用法