读Ext之一(实用方法)
第一句
1 | window.undefined = window.undefined; |
兼容IE6以下的浏览器,有人 解释过了。
定义Ext全局变量
1 2 3 | Ext = { version : '3.1.0' }; |
注意这里没有使用var,不使用var声明变量被认为是不好的编程习惯,尤其是函数内声明变量不写var更被称为是无穷无尽的Bug根源。这里则不会,因为变量Ext是该库唯一的全局变量(命名空间)。其它Ext源码中的变量声明都加上了var。
给Ext添加静态apply方法,该方法是核心方法之一,会用其扩展Ext。
1 2 3 4 5 6 7 8 9 10 11 12 | Ext.apply = function (o, c, defaults){ // no "this" reference for friendly out of scope calls if (defaults){ Ext.apply(o, defaults); } if (o && c && typeof c == 'object' ){ for ( var p in c){ o[p] = c[p]; } } return o; }; |
该方法有两种执行方式:
其一,只传o,c时直接将c上的所有属性/方法拷贝给o后返回;
其二,defaults也传时,会将defaults,c上的所有属性/方法都拷贝给o。这里实现的很巧妙,同时有点绕人。
三个参数都传,会执行Ext.apply(o, defaults),即自身实现中调用自身。defaults为c,即当传两个参数时会直接进行对象拷贝。举个例子一目了然,在Ext.apply中加上一个输出语句
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Ext.apply = function (o, c, defaults){ // no "this" reference for friendly out of scope calls if (defaults){ Ext.apply(o, defaults); } if (o && c && typeof c == 'object' ){ for ( var p in c){ alert(p); // 此处是添加的输出语句 o[p] = c[p]; } } return o; }; var obj = {}, obj1 = {name: 'jack' }, obj2 = {age:33}; Ext.apply(obj,obj1,obj2); |
会发现先弹出age,再是name。即先拷贝defaults,再是c。
接下来是个自执行的匿名函数,执行完后给Ext上扩充许多实用属性或方法。先定义了一些局部变量idSeed,浏览器判断之类。idSeed在做Dom缓存时用到。接下来,
1 2 3 4 5 | if (isIE6){ try { DOC.execCommand( "BackgroundImageCache" , false , true ); } catch (e){} } |
这段代码用来解决IE6下css背景图不缓存bug,也 有人 解释过了。
接下就是一个Ext.apply(Ext,{...}),给Ext对象扩展许多实用属性及方法。
注意 Ext.isStrict 并非判断html文档模式为严格模式,而是指标准模式,如<!DOCTYPE HTML>声明会返回true。关于文档模式猛击:http://hsivonen.iki.fi/doctype ,国内的 秦歌 翻译了该篇文章。
Ext.isSecure 判断采用https或是其它。
Ext.applyIf 设计的很巧妙,它会把对象没有的属性和方法拷贝下来,已经有的则不拷贝。Ext.apply 则会覆盖已有的属性/方法。
ECMAScript 5已经发布1年多了,添加了一些新的API方法,如Array的indexOf,forEach等方法,部分新版本浏览器已经支持这些方法来,但我们想为老的浏览器扩展该方法。可能会这样写
1 2 3 4 5 6 7 8 9 10 11 | var proto = Array.prototype; if (!proto.indexOf){ proto.indexOf = function (){ // ... } } if (!proto.forEach){ proto.forEach = function (){ // ... } } |
Ext.id方法会为HTMLElement元素随机生成一个id,默认以"ext-gen"开头。
接下来是Ext.extend方法,该方法也是核心方法之一,整个ext框架继承都是以该方法来扩展的。该方法实现依赖于Ext.override,先看override
1 2 3 4 5 6 7 8 9 | override : function (origclass, overrides){ if (overrides){ var p = origclass.prototype; Ext.apply(p, overrides); if (Ext.isIE && overrides.hasOwnProperty( 'toString' )){ p.toString = overrides.toString; } } } |
将对象overrides的所有属性/方法拷贝到类origclass的原型上。需要注意的是后面的if判断,IE中for in不能遍历对象的Object的toSting等方法,因此需要特别处理一下。我测试IE9 beta重写对象的内置方法如toString后是可用for in遍历的,见 for in的缺陷 。IE9 beta刚刚发布,不知今后Ext团队是否会修改此处的判断。
Ext.extend是js继承最经典的实现方式了,我曾经模仿其(简化版)应用在 51ditu 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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 (Ext.isObject(sp)){ 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.superclass = sbp.supr = ( function (){ return spp; }); sbp.override = io; Ext.override(sb, overrides); sb.extend = function (o){ return Ext.extend(sb, o);}; return sb; }; }(), |
整体浏览,可以看到 Ext.extend 的实现是通过一个匿名函数执行,执行后返回function,这个function才是真正的Ext.extend。
匿名函数中有两个私有函数io,oc。这种组织代码的方式非常简练,通过匿名函数自执行,在匿名函数中你可以做任何复杂的操作,最终的目的返回需要的接口函数或类。
有三个参数,sb、sp、overrides分别代表subClass(子类)、superClass(父类)及覆盖子类的配置参数。
以下分三种情况讨论,第一,二种情况Ext.extend的第二个参数都是对象类型
1, Ext.extend不光是用来实现类继承的,还可以用来写类,一年前 讨论 过 。
2, 用来扩展Ext库自身类,这种情况是比较频繁的
1 2 3 4 5 6 7 8 | MyGridPanel = Ext.extend(Ext.grid.GridPanel, { constructor: function (config) { MyGridPanel.superclass.constructor.apply( this , arguments); }, yourMethod: function () { // etc. } }); |
这里以Ext.grid.GridPanel为基础,生成了一个新类MyGridPanel
3, 真正意义类继承,即第一,二个参数都是类(function)。1年前也总结过js如何实现 继承 及 工具函数 。
篇幅已经很长了,重点说下 Ext.apply, Ext.applyif, Ext.override, Ext.extend 的区别 :
Ext.apply, Ext.applyif, Ext.override 都是对对象 进行扩展的方法,Ext.extend则是对类 操作的方法。
Ext.apply 扩展时对已经存在的属性/方法会被覆盖掉, 通常用它来扩展普通对象.
Ext.applyif 扩展时不会覆盖已经存在的属性/方法,通常用它来扩展核心js,如Array.prototype,String.prototype等。
Ext.override 扩展某一个类的原型,可以覆盖toString方法。
Ext.extend 用来写类或继承,或者说用来扩展类。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端