13.Ext.extend用法以及代码解读
转自:http://www.blogjava.net/dragonshrimp/archive/2008/03/01/183060.html
Ext.extend用法以及代码解读
概述
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下都是如此。那么我就不是很清楚这段代码到底是什么用的了,若有清楚的,告诉一声,哈。
13.Ext.extend用法以及代码解读的更多相关文章
- jquery,extjs中的extend用法小结
在jquery中,extend其实在做插件时还是用的比较多的,今天同时小结jquery和ext js中 的extend用法,先来看jquery中的. 1) extend(dest,src1,src2 ...
- Android MVP模式 谷歌官方代码解读
Google官方MVP Sample代码解读 关于Android程序的构架, 当前(2016.10)最流行的模式即为MVP模式, Google官方提供了Sample代码来展示这种模式的用法. Repo ...
- 【Ext.Net学习笔记】02:Ext.Net用法概览、Ext.Net MessageBus用法、Ext.Net布局
Ext.Net用法概览 Ext.Net还是很强大,如果运用熟练可以极大的提高编程效率.如果你也要学习Ext.Net,原文博主推荐书籍:<Ext.Net Web 应用程序开发教程>,是英文的 ...
- Jsoup代码解读之四-parser
Jsoup代码解读之四-parser 作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性.这部分也是Jsoup最复杂的部分,需要一些数据结构.状态机乃至编译器的知识.好 ...
- MXNet--DMLC-Core代码解读与宏
MXNet--DMLC-Core代码解读与宏 dmlc-core是Distributed (Deep) Machine Learning Community的一个基础模块,这个模块用被应用到了mxne ...
- 【dlib代码解读】人脸检测器的训练【转】
转自:http://blog.csdn.net/elaine_bao/article/details/53046542 版权声明:本文为博主原创文章,转载请注明. 目录(?)[-] 综述 代码解读 ...
- 18. 视图Ext.Viewport和窗口Ext.Window用法
转自:http://www.cnblogs.com/linjiqin/archive/2011/06/22/2087003.html 视图Ext.Viewport和窗口Ext.Window用法. 1. ...
- 优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案
简介 本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发 ...
- Ext.GridPanel 用法总结(一)—— Grid基本用法
Ext.GridPanel 用法总结(一)—— Grid基本用法 摘自:http://www.cnblogs.com/luluping/archive/2009/08/01/1536645.html ...
随机推荐
- php实现文件的下载
<?php$file_name="test.mp4";//需要下载的文件$fp=fopen($file_name,"r+");//下载文件必须先要将文件打 ...
- [SPOJ8222]Substrings
[SPOJ8222]Substrings 试题描述 You are given a string S which consists of 250000 lowercase latin letters ...
- Python模块:logging、
logging模块: 很多程序都有记录日志的需求,并且日志中包含的信息既有正常的程序访问日志,还可能有错误.警告等信息输出.Python的logging模块提供了标准的日志接口,你可以通过它存储各种格 ...
- ***CodeIgnite/CI 去掉 index.php的 配置
CI有效删除URL中的index.php 参考: http://codeigniter.org.cn/forums/thread-15444-1-1.html 读CI的使用手册的话,关于如何有效删除U ...
- 源码SDWebImage
源码来源:https://github.com/rs/SDWebImage 版本: 3.7 SDWebImage是一个开源的第三方库,它提供了UIImageView的一个分类,以支持从远程服务器下载并 ...
- 【c++】【转】C++ sizeof 使用规则及陷阱分析
http://www.cnblogs.com/chio/archive/2007/06/11/778934.html sizeof不是函数,更像一个特殊的宏,它是在编译阶段求值得.sizeof作用范围 ...
- 【转】深入理解javascript作用域——词法作用域和动态作用域
前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极易出错.这实际上是由两种作用域工作 ...
- C# .NET 如何批量增加或取消注释
选中一批文本之后 批量增加注释:Ctrl+K Ctrl+C 批量取消注释:Ctrl+K Ctrl+U
- HDU1215--七夕节
找出小于N的全部因子的和,N比較大,非常明显要打表来做,不然肯定会超时 方法就是枚举范围内每一个整数.然后再枚举范围内这个整数的全部的倍数,加上这个数 由于这个整数的倍数中一定含有这个整数因子,这样速 ...
- vue组件之间的通信,父子之间的数据通信
父子组件之间的通信问题既可以传递数据也可以传递变量,父组件传递数据给子组件可以使用props,子组件传递数据给父组件则可以自定义函数来监听子组件的事件发射器. 首先说说组件注册,组件的注册分为全局注册 ...