转自: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. leetcode-240搜索二维矩阵II

    搜索二维矩阵II class Solution: def searchMatrix(self, matrix, target): """ :type matrix: Li ...

  2. 集训第六周 数学概念与方法 数论 线性方程 I题

    Description The Sky is Sprite. The Birds is Fly in the Sky. The Wind is Wonderful. Blew Throw the Tr ...

  3. package control(转载)

    Package Control(扩展包管理器)   []Package Control 可以看做是一个ST的扩展管理器,可以去下载.安装.删除 Sublime Text 3的各种插件.皮肤等.   [ ...

  4. 将Java程序打包成可执行EXE文件的步骤

    需要的工具myeclipse .jar2exe(附上下载地址,直接解压就可以用链接: https://pan.baidu.com/s/1qYPRgXu 密码: wbva) 1.将Java项目导出成.j ...

  5. Mongo的Replica Sets (复制集)的配置全过程和心得体会

    http://blog.csdn.net/bloggongchang/article/details/7272403 一.MongoDB Replica Sets(副本集)简单的说就是有自动故障恢复功 ...

  6. Java 学习(5):修饰符 运算符

    目录 --- 修饰符 --- 运算符 --- 循环结构 --- 分支结构 修饰符: 修饰符用来定义类.方法或者变量,通常放在语句的最前端.如下: public class className { // ...

  7. 桐桐的糖果计划(vijos 1325)

    背景 桐桐是一个快乐的小朋友,他生活中有许多许多好玩的事,让我们一起来看看吧…… 描述 桐桐很喜欢吃棒棒糖.他家处在一大堆糖果店的附近. 但是,他们家的区域经常出现塞车.塞人等情况,这导致他不得不等到 ...

  8. bzoj1834 网络扩容 网络流

    好久没写题解了啊··· 题目大意: 给你一幅n个点的网络,先求出其1到n的最大流,每条弧还会有个属性\(cost_i\),表示没扩容一个单位的费用,现在我们要求的就是扩容K个单位的最小费用 思路: 这 ...

  9. HDU 2222 (AC自动机)

    HDU 2222 Keywords search Problem : 给若干个模式串,询问目标串中出现了多少个模式串. Solution : 复习了一下AC自动机.需要注意AC自动机中的fail,和n ...

  10. vim状态栏的扩充

    将以下内容添加到~/.vimrc文件中: set statusline= set statusline+=%7*\[%n]                                  " ...