转自: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用法以及代码解读的更多相关文章

  1. jquery,extjs中的extend用法小结

    在jquery中,extend其实在做插件时还是用的比较多的,今天同时小结jquery和ext js中 的extend用法,先来看jquery中的. 1)  extend(dest,src1,src2 ...

  2. Android MVP模式 谷歌官方代码解读

    Google官方MVP Sample代码解读 关于Android程序的构架, 当前(2016.10)最流行的模式即为MVP模式, Google官方提供了Sample代码来展示这种模式的用法. Repo ...

  3. 【Ext.Net学习笔记】02:Ext.Net用法概览、Ext.Net MessageBus用法、Ext.Net布局

    Ext.Net用法概览 Ext.Net还是很强大,如果运用熟练可以极大的提高编程效率.如果你也要学习Ext.Net,原文博主推荐书籍:<Ext.Net Web 应用程序开发教程>,是英文的 ...

  4. Jsoup代码解读之四-parser

    Jsoup代码解读之四-parser 作为Java世界最好的HTML 解析库,Jsoup的parser实现非常具有代表性.这部分也是Jsoup最复杂的部分,需要一些数据结构.状态机乃至编译器的知识.好 ...

  5. MXNet--DMLC-Core代码解读与宏

    MXNet--DMLC-Core代码解读与宏 dmlc-core是Distributed (Deep) Machine Learning Community的一个基础模块,这个模块用被应用到了mxne ...

  6. 【dlib代码解读】人脸检测器的训练【转】

    转自:http://blog.csdn.net/elaine_bao/article/details/53046542 版权声明:本文为博主原创文章,转载请注明.   目录(?)[-] 综述 代码解读 ...

  7. 18. 视图Ext.Viewport和窗口Ext.Window用法

    转自:http://www.cnblogs.com/linjiqin/archive/2011/06/22/2087003.html 视图Ext.Viewport和窗口Ext.Window用法. 1. ...

  8. 优秀开源代码解读之JS与iOS Native Code互调的优雅实现方案

    简介 本篇为大家介绍一个优秀的开源小项目:WebViewJavascriptBridge. 它优雅地实现了在使用UIWebView时JS与ios 的ObjC nativecode之间的互调,支持消息发 ...

  9. Ext.GridPanel 用法总结(一)—— Grid基本用法

    Ext.GridPanel 用法总结(一)—— Grid基本用法 摘自:http://www.cnblogs.com/luluping/archive/2009/08/01/1536645.html ...

随机推荐

  1. Python 3安装体验篇(win10)

    一.下载 1.打开官网https://www.python.org/downloads/windows/,点击Python 3版本链接 2.点击win10 64位安装链接,即可下载Python安装 二 ...

  2. Spider-scrapy断点续爬

    scrapy的每一个爬虫,暂停时可以记录暂停状态以及爬取了哪些url,重启时可以从暂停状态开始爬取过的URL不在爬取 实现暂停与重启记录状态 方法一: 1.首先cd进入到scrapy项目里(当然你也可 ...

  3. 集训第四周(高效算法设计)N题 (二分查找优化题)

    原题:poj3061 题意:给你一个数s,再给出一个数组,要求你从中选出m个连续的数,m越小越好,且这m个数之和不小于s 这是一个二分查找优化题,那么区间是什么呢?当然是从1到数组长度了.比如数组长度 ...

  4. SQL SERVER占用CPU过高排查和优化

    操作系统是Windows2008R2 ,数据库是SQL2014 64位. 近阶段服务器出现过几次死机,管理员反馈机器内存使用率100%导致机器卡死.于是做了个监测服务器的软件实时记录CPU数据,几日观 ...

  5. Java中static、final、static final的区别

    final: final可以修饰:属性,方法,类,局部变量(方法中的变量) final修饰的属性的初始化可以在编译期,也可以在运行期,初始化后不能被改变. final修饰的属性跟具体对象有关,在运行期 ...

  6. Webdriver概述(selenium对应浏览器版本)

    Webdriver (Selenium2)是一种用于Web应用程序的自动测试工具,它提供了一套友好的API,与Selenium 1(Selenium-RC)相比,Webdriver 的API更容易理解 ...

  7. UVALive 6507 Passwords

    Passwords Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ...

  8. poj1655(dfs,树形dp,树的重心)(点分治基础)

    题意:就是裸的求树的重心. #include<cstring> #include<algorithm> #include<cmath> #include<cs ...

  9. JDK源码解析(一)ArrayList源码解析

    这里为了方便写注释,我是把ArrayList的源码复制下来放到自己创建的类里面的 这个变量则指向具体存放数据的数组 看下构造函数吧 点进去看下LinkedList是怎么数组化的 很弱智吧,就是创建一个 ...

  10. spring security 5.0 密码未加密报错

    使用spring security5.0后,配置文件中直接写普通的密码如:123456,会报错: java.lang.IllegalArgumentException: There is no Pas ...