extend这个函数,在JS中,被赋予了各种神奇的功效,特别是在继承和各种对象操作中,起着很大的作用,
可以说,extend撑起了不少库的半边天,虽然有时它扮演的角色和作用不完全相同.
一.简单的类继承
刚开始接触extend函数,大家可能是在学习JS的继承的时候.为了简化派生子类的过程,这时神奇的extend出现了
1 | function extend(subClass,superClass){ |
4 | F.prototype=superClass.prototype; |
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; |
这个函数,封装了继承中的细节,是实现类式继承,十分重要的部分,使用了一个F空函数作为过渡,可以避免
创建父类的实例.下面的代码更多是为了弱化代码耦合,可以使用superClass属性调用父类构造函数.
二.Prototype.js
接下来,最有可能接触的,必定是Prototype库的extend函数,曾经有大神说,离开extend函数,Prototype就无法成为Prototype了,可见extend函数对于Prototype的重要性.
在Prototype 1.3 框架中 给每个对象都定义了extend方法,
1 | //Prptotype库的extend,为Object类添加静态方法, |
2 | Object.extend=function(destination,source) { |
3 | for(property in source) { |
4 | destination[property]=source[property]; |
9 | Object.prototype.extend = function(object) { |
10 | return Object.extend.apply(this, [this, object]); |
第一个函数Object.extend,可以简单的理解为对象复制.目标对象将拥有源对象的所有属性和方法
第二个函数Object.prototype.extend,在prototype对象中加上一个extend函数,
其中精华语句Object.extend.apply(this, [this, object]); 将Object对象中的extend作为静态方法调用,
第一个参数this,指向调用对象本身,第二个参数,为一个数组,为调用对象本身和传递进来的对象参数object(一般为方法,下面有例子)
那么说了那么多.如何实现继承呢?Prototype是这样实现的
12 | son.prototype=(new father()).extend({ |
这样就实现了继承,先写这么多吧,其他两个框架,过几天再写.
各种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 类库的起始位置,可见它的重要性
1 | Ext.apply = function(o, c, defaults){ |
2 | //如果提供defaults对象,可以在复制父对象之前,实现自己方法和属性 |
4 | Ext.apply(o, defaults); |
7 | if(o && c && typeof c == 'object'){ |
从上面代码可以看出 apply 有点类似 Prototype 的 Object.extend 做了个简单的对象复制,但是它扩展了一个功能,就是可以在复制之前,先添加自己的方法和属性,当然这个函数会覆盖原有的属性,如果要想不要覆盖可以使用 applyIf 函数.
1 | applyIf : function(o, c){ |
4 | if(!Ext.isDefined(o[p])){ |
有对象继承,就肯定有类继承啦.接下来可以再看下 Ext.override 实现类继承
1 | /* @param {Object} origclass 要进行覆盖的类 |
2 | * @param {Object} 应该是一个包含一个或更多方法的对象字面量,将一系列的方法添加到origClass中 |
4 | *实现了将overrides,复制到origclass的prototype中去,从而实现了类继承. |
6 | override : function(origclass, 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; |
说了这么多,终于到了 extend 了吧!!果断上代码!!
1 | /* @param {Function} subclass 子类, |
2 | * @param {Function} superclass 父类, |
3 | * @param {Object} overrides 一些增加的方法和属性,将覆盖到子类中 |
4 | * @return {Function} 如果没有指定子类,将生成返回,反而,返回extended后的子类 |
13 | var oc = Object.prototype.constructor;//为后面生成子类构造函数的判断做准备 |
15 | //自执行函数,返回实际的extend函数内容 |
16 | return function(sb, sp, overrides){ |
21 | //如果overrides的构造函数是Object,生成子类的构造函数,即可以在overrides携带构造函数, |
23 | sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; |
25 | //空函数,避免修改父类的prototype |
31 | //原型继承,如果无法理解可见本系列的上一篇文章 |
32 | sbp = sb.prototype = new F(); |
33 | //修改子类的prototype的构造函数指向子类构造函数 |
35 | //指定子类的superclass为父类的prototype |
37 | //将父类的prototype的构造函数指向父类构造函数 |
38 | if(spp.constructor == oc){ |
42 | sb.override = function(o){ |
45 | //指定子类的prototype的superclass属性为父类的prototype |
46 | sbp.superclass = sbp.supr = (function(){ |
49 | //指定子类的prototype的override |
51 | //将overrides所有方法和属性复制到子类中 |
52 | Ext.override(sb, overrides); |
54 | sb.extend = function(o){return Ext.extend(sb, o);}; |
实践才是硬道理!!下面上"栗子"!!
2 | var SonClass=Ext.extend(FatherClass,{/*各种房子,美女,豪车,任你添加*/}); |
4 | var SonClass=Ext.extend(FatherClass,{constructor:function(){/*构建子类*/}}); |
6 | var SonClass=function(config){ |
7 | SonClass.superclass.constructor.call(this,config); |
9 | Ext.extend(SonClass,FatherClass,{/**/}); |
由此可见,Ext的继承是在(一)中提到了简单继承发展起来的,并实现了更加强大的功能,支持完美的对象继承,类继承,生成子类继承,十分灵活,Ext在 extend 和 apply 和 override 三大的函数的配合下,完美实现了JS继承,为整个Extjs的面向对象和组件级应用打下了坚实的基础.
到此,Ext的extend已经解析完毕,真长啊,大家拍砖抓紧
以上源码分析基于 Ext js 3.1 目前最新版本请链接官网