各种Extend--Prototype,Ext,Jquery中Extend的比较(一)

extend这个函数,在JS中,被赋予了各种神奇的功效,特别是在继承和各种对象操作中,起着很大的作用,
可以说,extend撑起了不少库的半边天,虽然有时它扮演的角色和作用不完全相同.

一.简单的类继承

刚开始接触extend函数,大家可能是在学习JS的继承的时候.为了简化派生子类的过程,这时神奇的extend出现了

1function extend(subClass,superClass){
2    //引入空函数,避免创建父类的新实例
3    var F=function(){};
4    F.prototype=superClass.prototype;
5    //创建拷贝,不影响父类
6    subClass.prototype=new F();
7    //提供superClass属性,弱化父子类间耦合
8    subClass.prototype.constructor = subClass;
9    subCLass.superClass=superClass.prototype;
10    if(superClass.prototype.constructor == Object.prototype.constructor){
11        superClass.prototype.constructor=superClass;
12    }
13}

这个函数,封装了继承中的细节,是实现类式继承,十分重要的部分,使用了一个F空函数作为过渡,可以避免
创建父类的实例.下面的代码更多是为了弱化代码耦合,可以使用superClass属性调用父类构造函数.

二.Prototype.js

接下来,最有可能接触的,必定是Prototype库的extend函数,曾经有大神说,离开extend函数,Prototype就无法成为Prototype了,可见extend函数对于Prototype的重要性.

在Prototype 1.3 框架中 给每个对象都定义了extend方法,

1//Prptotype库的extend,为Object类添加静态方法,
2Object.extend=function(destination,source) {
3    for(property in source) {
4        destination[property]=source[property];
5    }
6    return destination;
7}
8//通过Object类,为每个对象,添加方法
9Object.prototype.extend = function(object) {
10  return Object.extend.apply(this, [this, object]);
11}

第一个函数Object.extend,可以简单的理解为对象复制.目标对象将拥有源对象的所有属性和方法
第二个函数Object.prototype.extend,在prototype对象中加上一个extend函数,
其中精华语句Object.extend.apply(this, [this, object]); 将Object对象中的extend作为静态方法调用,
第一个参数this,指向调用对象本身,第二个参数,为一个数组,为调用对象本身和传递进来的对象参数object(一般为方法,下面有例子)

那么说了那么多.如何实现继承呢?Prototype是这样实现的

1//定义父类father
2function father(){
3}
4father.prototype={
5    //各种方法
6}
7 
8//定义子类son
9function son(){
10}
11 
12son.prototype=(new father()).extend({
13        //新添加方法
14        ....
15});

这样就实现了继承,先写这么多吧,其他两个框架,过几天再写.

 

 

各种Extend--Prototype,Ext,Jquery中Extend的比较(二)

Ok,继续各种 Extend--Prototype,Ext,Jquery中Extend的比较(一) 文中所述,我将在接下来介绍 Ext js 中的继承和 Extend.

在接下去之前,再写写关于Prototype 1.3 的 extend ,将继承功能直接扩展在Object对象中,这样会污染了整个Object,对反射操作影响,后来作者果断在后续版本放弃对Object对象原型中扩展继承.

很多人(包括著名的JSON之父 D.C )就是诟病Prototype.js污染了原生对象的prototype和污染命名空间.虽然 Prototype.js 是个很优秀的框架,但是被 YUI , dojo , jQuery 不污染原型的框架联合打击,渐渐式微了..

曾经有很多优秀的库,都是基于 Prototype 的,例如用于 WebGIS 客户端的著名的 OpenLayers ,还有全世界最出名的特效库 Script.aculo.us (可能撞墙).

Prototype 目前最新版本详情可以查看官网.

三.Ext JS的继承

接下来,说下本人刚开始是研究的框架 Ext JS.如果说 Jquery 是把锋利的小刀, YUI 是把无锋的重剑,另外 John Resig 和 N C.Zakas 关于两者的辩论,大家可以去围观下拔刺的翻译

那么基于 Yahoo-UI 的 Ext JS 可以说是一把厚重的大斧,主要用于企业应用系统的开发,属于应用级框架,基于组件级的 Ext js ,的确有它独特的特点,特别是它的UI界面,可以节省很多开发时间,再者由于 Ext 是高度基于面向对象的编程思想,封装性和扩展性也相当好.正是基于这两个特点,一个从来没有接触过Ext的初学者,可以直接从Demo中,学习和掌握这个框架的一本应用.但是,正是由于这个特点,对于想在 javascript 加深认识的初学者,这个框架不是一个很好的选择.

废话说完,下面回到正题.在剖析 extend 之前,先顺便介绍一下它的 apply 函数,这个函数实现了对象继承,注册在"Ext"的命名空间中,并放在了 Ext 类库的起始位置,可见它的重要性

1Ext.apply = function(o, c, defaults){
2    //如果提供defaults对象,可以在复制父对象之前,实现自己方法和属性
3    if(defaults){
4        Ext.apply(o, defaults);
5    }
6    //反射复制
7    if(o && c && typeof c == 'object'){
8        for(var in c){
9            o[p] = c[p];
10        }
11    }
12    return o;
13};

从上面代码可以看出 apply 有点类似 Prototype 的 Object.extend 做了个简单的对象复制,但是它扩展了一个功能,就是可以在复制之前,先添加自己的方法和属性,当然这个函数会覆盖原有的属性,如果要想不要覆盖可以使用 applyIf 函数.

1applyIf : function(o, c){
2        if(o){
3            for(var in c){
4                if(!Ext.isDefined(o[p])){
5                    o[p] = c[p];
6                }
7            }
8        }
9        return o;
10    }

有对象继承,就肯定有类继承啦.接下来可以再看下 Ext.override 实现类继承

1/* @param {Object} origclass 要进行覆盖的类
2 * @param {Object} 应该是一个包含一个或更多方法的对象字面量,将一系列的方法添加到origClass中
3 * @method override
4 *实现了将overrides,复制到origclass的prototype中去,从而实现了类继承.
5 */
6override : function(origclass, overrides){
7    if(overrides){
8        var p = origclass.prototype;
9        Ext.apply(p, overrides);
10        //河蟹IE的一个bug,IE9好像修复了.待验证
11        if(Ext.isIE && overrides.hasOwnProperty('toString')){
12            p.toString = overrides.toString;
13        }
14    }
15}

说了这么多,终于到了 extend 了吧!!果断上代码!!

1/* @param {Function} subclass 子类,
2 * @param {Function} superclass 父类,
3 * @param {Object} overrides 一些增加的方法和属性,将覆盖到子类中
4 * @return {Function} 如果没有指定子类,将生成返回,反而,返回extended后的子类
5 */
6extend : function(){
7        // 利用闭包,私有方法和私有对象,内部访问
8        var io = function(o){
9            for(var in o){
10                this[m] = o[m];
11            }
12        };
13        var oc = Object.prototype.constructor;//为后面生成子类构造函数的判断做准备
14 
15        //自执行函数,返回实际的extend函数内容
16        return function(sb, sp, overrides){
17            //如果是两个参数,即sp为Object时
18            if(Ext.isObject(sp)){
19                overrides = sp;
20                sp = sb;
21                //如果overrides的构造函数是Object,生成子类的构造函数,即可以在overrides携带构造函数,
22                //后面有例子加以说明
23                sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
24            }
25            //空函数,避免修改父类的prototype
26            var F = function(){},
27                sbp,
28                spp = sp.prototype;
29 
30            F.prototype = spp;
31            //原型继承,如果无法理解可见本系列的上一篇文章
32            sbp = sb.prototype = new F();
33            //修改子类的prototype的构造函数指向子类构造函数
34            sbp.constructor=sb;
35            //指定子类的superclass为父类的prototype
36            sb.superclass=spp;
37            //将父类的prototype的构造函数指向父类构造函数
38            if(spp.constructor == oc){
39                spp.constructor=sp;
40            }
41            //为子类注册一个静态方法override
42            sb.override = function(o){
43                Ext.override(sb, o);
44            };
45            //指定子类的prototype的superclass属性为父类的prototype
46            sbp.superclass = sbp.supr = (function(){
47                return spp;
48            });
49            //指定子类的prototype的override
50            sbp.override = io;
51            //将overrides所有方法和属性复制到子类中
52            Ext.override(sb, overrides);
53            //为子类注册一个静态方法extend
54            sb.extend = function(o){return Ext.extend(sb, o);};
55            return sb;
56        };
57    }()

实践才是硬道理!!下面上"栗子"!!

1//第一种
2var SonClass=Ext.extend(FatherClass,{/*各种房子,美女,豪车,任你添加*/});
3//第二种
4var SonClass=Ext.extend(FatherClass,{constructor:function(){/*构建子类*/}});
5//第三种
6var SonClass=function(config){
7    SonClass.superclass.constructor.call(this,config);
8}
9Ext.extend(SonClass,FatherClass,{/**/});

由此可见,Ext的继承是在(一)中提到了简单继承发展起来的,并实现了更加强大的功能,支持完美的对象继承,类继承,生成子类继承,十分灵活,Ext在 extend 和 apply 和 override 三大的函数的配合下,完美实现了JS继承,为整个Extjs的面向对象和组件级应用打下了坚实的基础.

到此,Ext的extend已经解析完毕,真长啊,大家拍砖抓紧

以上源码分析基于 Ext js 3.1 目前最新版本请链接官网

 

posted on 2012-10-30 16:35  osccur123  阅读(1100)  评论(0)    收藏  举报