`

Ext.extend() 使用

阅读更多


一、从实际使用角度分析Ext.extend()函数
     还是先贴出Ext核心代码里面完成继承功能的这段经典代码:
extend : function(){
            // inline overrides
            var io = function(o){
                for(var m in o){
                    this[m] = o[m];
                }
            };
            var oc = Object.prototype.constructor;

            return function(sb, sp, overrides){
                if(typeof sp == 'object'){
                    overrides = sp;
                    sp = sb;
                    sb = overrides.constructor != oc ? overrides.constructor : 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 == oc){
                    spp.constructor=sp;
                }
                sb.override = function(o){
                    Ext.override(sb, o);
                };
                sbp.override = io;
                Ext.override(sb, overrides);
                sb.extend = function(o){Ext.extend(sb, o);};
                return sb;
            };
        }()
     使用Ext.extend()这个函数来做继承,可以有三种写法:
1、 子类本身有自己的构造函数;
2、 不提供子类自己的构造函数,使用父类的构造函数来构造子类;
3、 在第三个参数overrides里面提供一个constructor函数,然后在它的第一句调用父类的构造


来看第一种写法(子类有自己定义的构造函数),例如:
A=function(config){
    this.id=config.id;
}
A.prototype.sayHello=function(){
    alert(“function from Class A!”);
}
B=function(config){
    this.name=config.namel;
}
然后让B来继承A:
A=Ext.extend(A,B);(该行有误,多谢log4j兄指出)


正确写法是这样:

B=Ext.extend(B,A);


     但是,通过这种写法你会发现,超类A的属性(id)没有被B继承过来。
因为Ext.extend()函数里面的if(typeof sp == 'object'){…}不成立,在继承之后,子类B仅仅获得了超类的sayHello()方法。

第二种写法(不提供子类自己的构造函数):
C=Ext.extend(A,{});
这样的话子类C可以顺利地获得超类A的id属性和sayHello()方法

第三种写法(在overrides里面提供constructor):
例如overrides被定义成这样:
{
    constructor:function(config){
this.superclass.constructor.call(this.config);
}
}
     必须加一句调用:this.superclass.constructor.call,这句实际上是调用父类的构造器来使子类获得父类里面定义的参数。
但是这么做有一点不是很爽,例如我要自定义一个MyPanel来继承Ext.Panel,如果我想采用第三种写法,自己提供的overrides里面必须有如上的手工调用的语句。如果继承的层次稍微深一点,那么每次继承都要写同一句话,这显然是很不爽快的事情。


二、自己来构造一个extend函数
     继承的实质是什么?
     如果简单来说的话,它可以分两方面:一是从父类获得一些属性;二是从父类获得一些方法,从而达到代码复用的目的。
那么,来考虑如下情况:
有一个Plant类来描述植物,它有一个属性id,有一个方法grow(),那么这个类看起来可能是这样的:
Plant=function(config){
this.id=config.id;
}
Plant.prototype.grow=function(){
alert(“Plant grows…”);
}
     现在有Fruit类来描述水果,显然它继承自Plant类,它增加了一个属性isSweet来描述是不是甜的。
Fruit=function(config){
this.isSweet=config.isSweet;
}
     现在,如果用Ext的extend函数,可以这么写:Fruit=Ext.extend(Fruit,Plant);但是,这么写有个缺点,就是Fruit类并没有把父类Plant的id属性继承下来,而只是继承了父类的grow()方法。
那么,只能被迫采用第三种写法,提供一个overrides,然后在里面加个constructor。这显然不是很爽。我们期望的效果是,子类有自己的构造函数,同时还能把父类的属性和方法都继承下来。那么,我们就可以来尝试做个自己的继承工具。
     想一想JAVA里面的继承,在调用子类自己的构造函数之前,默认会调用一次父类的构造函数。那么,我们借鉴一下Ext.extend,使用闭包的原理,同时增加一点自己的内容:
MyUtil={};
MyUtil.extend=function(){
return function(sb,sp,overrides){
if(typeof sp =='object'){//没有传递子类的构造函数
overrides=sp;
sp=sb;
//继承父类属性
sb=function(){
sp.apply(this,arguments);
};
}else{//如果子类已经有自己定义的构造函数
var cache=sb;//把子类的构造函数先缓存起来
sb=function(){ //重新包装出一个构造函数
sp.apply(this,arguments);//首先调用父类的构造函数 cache.apply(this,arguments);//然后调用自身的构造函数
};
}
//继承父类方法
var sbp=sb.prototype;
var spp=sp.prototype;
A.apply(sbp,spp);
sb.constructor=sb;
A.apply(sb,overrides);
return sb;
}
}();

     好,有了如上的继承工具,就可以完成想要的功能,而且可以完成层次比较深的继承关系了。
     以下是一个完整的测试例子,直接引入到html里面可以看到结果。最低层的D类获得了所有超类的属性和方法。
MyUtil={};

MyUtil.apply=function(des,src,defaults){
if(defaults){
ExtSvg.apply(des,defaults);
}
if(des&&src&&typeof src=='object'){
for(var p in src){
des[p]=src[p];
}
}
return des;
};

MyUtil.extend=function(){
return function(sb,sp,overrides){
if(typeof sp =='object'){//没有传递子类的构造函数
overrides=sp;
sp=sb;
//继承父类属性
sb=function(){
sp.apply(this,arguments);
};
}else{//如果子类已经有自己定义的构造函数
var cache=sb;//把子类的构造函数先缓存起来
sb=function(){ //重新包装出一个构造函数
sp.apply(this,arguments);//首先调用父类的构造函数 cache.apply(this,arguments);//然后调用自身的构造函数
};
}
//继承父类方法
var sbp=sb.prototype;
var spp=sp.prototype;
A.apply(sbp,spp);
sb.constructor=sb;
A.apply(sb,overrides);
return sb;
}
}();

/**
* Class B
*/
B=function(paramObj){
this.id=paramObj.id;
this.meterName=paramObj.meterName;
}
B.prototype.BsayHello=function(){
alert(this.id);
}

/**
* Class C
*/
C=function(paramObj){
this.privateName=paramObj.name;
}
C=MyUtil.extend(C,B);
C.prototype.CsayHello=function(){
alert("This is the msg from Class C!");
}

/**
* Class D
*/
D=function(paramObj){
this.delay=paramObj.delay;
}
D=MyUtil.extend(D,C);
D.prototype.DsayHello=function(){
alert("This is the msg from Class D!");
}

/**
* test functioin
*/

var test=new C({id:'this is the id of class c!',name:'xiaofei',meterName:'meterName',delay:'delayed 3 days!'});
for(var p in test){
alert(p+"-->"+test[p]);
}

三、几句废话
     在通过原型链模拟出继承关系之后,脚本已经可以具备强大的功能,写出来的代码应该比较“面向对象”,而不是散落一地的一堆毫无关系的函数。但是,在实际使 用Ext这个优秀的js框架的时候,笔者发现,很多人(包括笔者自己)写出来的东西仍然是一堆函数。而没有能发挥出“继承”的威力。写出来的JS代码很长 很大,重复的代码非常多。
     鉴于这样的情况,笔者认为,在真正动手写JS之前,需要先好好分析一下一个页面的构成,里面有多少固定的东西,稍微封装一下再来做,情况会好很多。Ext这个类库非常优秀,千万不能把它当烧火棍来用啊!!

分享到:
评论

相关推荐

    Ext.Store的获取方法

    总结来说,在Ext.js中,获取`Ext.Store`应使用`Ext.getStore`方法,而不是`Ext.getCmp`,因为Store是通过`storeId`在内存中注册和管理的,而不是作为页面上的一个可视组件。同时,Store的设计方式有助于数据的安全性...

    Ext.data.Store 读取XML属性值

    extend: 'Ext.data.Model', fields: ['id', 'name', 'email'] }); var store = Ext.create('Ext.data.Store', { model: 'MyModel', proxy: { type: 'ajax', reader: { type: 'xml', record: 'item' // XML...

    Ext.ux.UploadDialog

    Most configuration options are inherited from Ext.Window (see ExtJs docs). The added ones are: url - the url where to post uploaded files. base_params - additional post params (default to {}). ...

    ext使用--Panel和iframe联合使用时页面高度的解决方法

    Ext.extend(Ext.layout.container.MyIFrameLayout, Ext.layout.container.Fit, { onLayout: function(ct, target) { var iframe = ct.items.first(); if (iframe && iframe.rendered) { var iframeBody = ...

    Ext.js核心函数详解.docx

    4. `Ext.extend( Object subclass, Object superclass, [Object overrides] )`: 这是实现面向对象编程的关键函数,它用于创建子类,将`subclass`扩展自`superclass`。`overrides`参数用于提供子类覆盖父类的方法或...

    Extjs 继承Ext.data.Store不起作用原因分析及解决

    关于这个原因有很多种,我只说下我遇到的 我这样 写Store来复用的 代码如下: DocStore = Ext.extend(Ext.data.Store,{ initComponent:function(){ this.proxy = new Ext.data.HttpProxy({url:this.url}); this....

    ext多选下拉列表的全选功能实现

    "ext多选下拉列表的全选功能实现"这个主题聚焦于一个特定的UI组件——ExtJS库中的MultiComboBox,这是一种允许用户多选的下拉列表控件。在实际应用中,全选功能常常被用来快速选择所有选项,极大地提高了用户的操作...

    Ext一些方法的重写

    在`ext-extend.js`这个文件中,可能包含了对`Ext.extend()`的进一步实现和扩展,或者展示了如何在实际项目中重写`Ext`库的方法。通常,这样的代码示例会包含具体的类定义、方法重写以及如何在应用中使用这些自定义类...

    Ext.js核心函数详解.pdf

    6. `Ext.extend(Object subclass, Object superclass, [Object overrides])`: 这是实现JavaScript继承的关键函数。`subclass`是子类,`superclass`是父类,`overrides`是子类要覆盖或扩展父类的方法。它创建了一个新...

    ExtJs 带清空功能的日期组件

    可以通过`Ext.extend()`方法实现这一点。 ```javascript Ext.define('MyApp.form.field.ClearableDate', { extend: 'Ext.form.field.Date', alias: 'widget.clearabledatefield', // 添加其他配置项... }); ``...

    Jquery实现$.fn.extend和$.extend函数

    使用这个模拟库,你可以像使用原生jQuery一样调用 `$.fn.extend` 和 `$.extend`: ```javascript _$_().fn.extend({myMethod: function() {console.log('My custom method!')}}) _$_().myMethod(); // 输出 "My ...

    EXtJS学习 EXtJS学习

    然而,在使用 `Ext.extend` 进行继承时,需要注意一些潜在的问题,特别是涉及到共享状态,如数组成员时。 在上述例子中,我们看到一个关于 `Ext.extend` 使用的一个有趣的陷阱。问题在于,当子类继承父类并试图修改...

    浅谈jquery.fn.extend与jquery.extend区别

    jQuery添加一个为 add的“静态方法”,之后便可以在引入 jQuery 的地方,使用这个方法了. 2.jQuery.fn.extend(object); 对jQuery.prototype进得扩展,就是为jQuery类添加“成员函数”。jQuery类的实例可以使

    ExtJS ToolTip功能

    extend:'Ext.container.Container', ... }); ``` 这行代码定义了一个名为`WebApp.view.tip.ToolTip`的新类,该类继承自`Ext.container.Container`。这意味着我们可以使用所有容器类的功能。 2. **布局配置**:...

    Ext继承和扩展

    然而,`Ext`库提供了一个更优雅、更易于理解和维护的方式来处理继承,这包括`Ext.extend()`方法和`Ext.create()`函数。 ### `Ext.extend()` `Ext.extend()`是`Ext`库中用于创建子类的核心方法。它接受三个参数:...

    EXT dojochina Ext类静态方法.rar

    EXT dojochina Ext类静态方法是一个关于EXT框架在JavaScript中的使用的主题,主要聚焦于Ext类的静态方法。EXT是一个强大的前端开发框架,由Sencha公司开发,它提供了丰富的组件库,用于构建复杂的Web应用程序。在EXT...

    Ext Js权威指南(.zip.001

    7.2.10 使用浏览器存储的代理:ext.data.webstorageproxy、ext.data. sessionstorageproxy和ext.data.proxy.localstorage / 314 7.3 读取和格式化数据 / 315 7.3.1 概述 / 315 7.3.2 数据的转换过程:ext.data....

Global site tag (gtag.js) - Google Analytics