1.Ext.lib.Ajax
应该是从 YUI 借鉴过来的,没有看过 YUI 源码,它的工作方式确实比较独特,没有采用常见的判断 readystatechange ,而是自己定时轮训查看状态
好处:可以随时终止,只要不轮训就可以了么(例如超时判断),否则 readystatechange 的话,超时就比较麻烦,回调函数仍然会被调用,只有在回调函数中判断了是否超时了。
ps:这种情况也可采取直接将 readystatechange=null 即可。
坏处:可能不是事件发生的同时处理,有点滞后,不过50ms的轮训事件已经很短了。
2.Ext.util.TaskRunner
这个有存在的必要么?原先可以多个 interval 处理的东西 ,由 taskrunner 管理的话,集中由一个 很短的interval 管理,有什么好处?
3.Ext.lib.AnimBase
Anim 一块非常复杂,Ext 将各个功能解耦:
Ext.lib.AnimBase : 框架每个想要动画的元素父类
Ext.lib.AnimBase的子类:表示元素具体要哪方面的动画
Ext.lib.ColorAnim:颜色渐变等
Ext.lib.Motion:平滑移动等
Ext.lib.Scroll:平滑滚动等
runtimeAttributes = {} : 记录动画属性 在动画过程中的具体变化
Ext.lib.Easing 由 Ext.lib.AnimBase 调用,元素从一个位置变到下一个位置的值,很多计算方式
Ext.lib.AnimMgr 调度Ext.lib.AnimBase的集合,各个动画 统一 interval 调度
由于每个setTimeout会由浏览器新开一个线程来处理,那么当settimeout很多时,浏览器就会不可思议的慢。( Efficient Javascript )
让我们看看John Resig 是怎么评价的 :
(From Secrets of the JavaScript Ninja)
对计时器进行中央控制的好处:
1.一个页面可以同时只有一个计时器在运行
2.你可以随时暂停或继续所有计时器
3.很容易移除回调函数
增加并发的计时器很可能导致浏览器的垃圾回收行为,认识到这一点很重要,垃圾回收简单地说就是浏览器解开节的过程 (删除无用的变量,对象等等),因为计时器脱离正常的javascript引擎控制的流程(通过其他线程), 有些浏览器很擅长处理这种情况,但是有些浏览器就会导致很长的垃圾回收周期,你可能遇到过这种情况,在一个浏览器中 流畅进行的动画在另一个浏览器就变得拖拖拉拉,或者刚开始就结束。所以减少并发的计时器非常有必要(这就是为什么现代的 动画引擎都是只有一个全局控制计时器)
例子:如何把不同属性的动画设置过程用一个计时器来实现
<div id="box" style="position:absolute;">Hello!</div> <script type="text/javascript"> var timers = { timerID: 0, timers: [], start: function(){ if (this.timerID ) return; (function(){ for ( var i = 0; i < timers.timers.length; i++ ) { if ( timers.timers[i]() === false ) { timers.timers.splice(i, 1); i--; } } timers.timerID = setTimeout( arguments.callee, 0 ); })(); }, stop: function(){ clearTimeout( this.timerID ); this.timerID = 0; }, add: function(fn){ this.timers.push( fn ); this.start(); } }; var box = document.getElementById("box"), left = 0, top = 20; timers.add(function(){ box.style.left = left + "px"; if ( ++left > 50 ) return false; }); timers.add(function(){ box.style.top = top + "px"; top += 2; if ( top > 120 ) return false; }); </script>
这样我们创造了一个中央计时器结构,我们可以随时添加回调函数,并且可以开始停止 这个中央计时器,并且每个回调函数可以返回false来随时终止他们的运行,这比 调用clearTimeout的方式简单多了。
代码详解:
所有的回调函数被保存在一个中央队列(timers.timers),还有中央计时器(timers.timeID), 真正能够开始函数是start(),我们首先检查中央计时器是否已经运行,没有的话就是它运行。
中央处理器遍历所有的回调函数,依次执行。如果回调函数返回值是false,那么 该回调函数从当前队列中移除,这是一种比传统模式简单的停止方法。
另外一点需要注意的是:这种形势下回调函数会以他们添加的次序被执行, 传统的定时器并不能保证这点(浏览器有时会神智会乱 :()
这种定时器的管理方法对于大型应用或者任何形式的动画引擎都非常重要,并且对于 项目后期扩展以及跨浏览器的应用非常有帮助。
4.Ext.Template
大量的利用了 String 的 replace 这个函数
compile 非常精巧,利用 javascript 语言特性动态产生特定模板函数 ,对于一个模版固定,数据经常变化的场合提高系统效率,否则每次正则查找确实很低效。
ps:传统技术中也有类似的应用,例如 "即时代码生成 "技术, 函数可以在运行时查看各参数值,然后为它的函数体生成更加高效的,直接针对特定参数值执行的代码,然后跳到这些代码去运行。
特定的模版函数可以产生特定模板汇合不同数据而产生结果字符串,细节,ie 用了 数组join提高效率,ff 则不用了直接用 + ,可见 ff 对字符串concat优化了,不用我们特殊考虑。
09-09-08 note:
关于 string 的 加操作,Nicholas C. Zakas 在even faster websites 中也有提到:
从firefox1.0开始,对string的+操作进行了优化,使得直接+操作在任何情况下都要比比array join要快,其他浏览器如chrome,safari,opera,ie8都做了上述优化,而ie8以下的版本则没有优化.
当string长度增长(20+)以及+操作次数增大(1000+)时,ie8以下版本array join方法比+方法越来越快,firefox,safari则两种方法性能越来越接近,当然+操作仍然稍快点,而chome和opera则+方法无论如何都比array join方法会很多.
总结:
所以你可以象ext一样区分浏览器对待,但是一般情况下用+即可.