当前位置: 代码迷 >> Web前端 >> Ext.get()与Ext.fly()之差异
  详细解决方案

Ext.get()与Ext.fly()之差异

热度:217   发布时间:2012-10-18 13:46:55.0
Ext.get()与Ext.fly()之区别
转自:渔人码头&超人&米米

Ext.get()与Ext.fly()之区别


从一开始接触Ext就看到有Ext.fly这个函数,当时觉得这个跟Ext.get没什么区别,加之当时对JS性能相关
问题认识肤浅,也一直没有在意其区别,今日看learning extjs一书,看到了有专门对Ext.fly特别强调的一处:

This?isn't?exactly?a?speed?tip,?but?is?more?about?conserving?memory?by?using?something?called?
a?"flyweight"?to?perform?simple?tasks,?which?results?in?higher?speed?by?not?clogging?up?the?
browser's?memory

大概意思也就是Ext.Fly采用flyweight模式使所有fly出来的元素共享内存,可以提高程序执行速度,减少内存占用。

??????? 这段话激起了我对这个函数的兴趣,毕竟近段时间一直在搞JS性能优化相关问题,对“内存”这个字眼
非常敏感。大概看了下Ext源码对get和fly实现的部分,然后在网上查看了一些资料,终于对他们之间的异同有
了个比较深入的认识。
Ext的官方开发人员给出了如下的解释:

Ext.Element?wraps?a?lot?of?functionality?around?DOM?element/node,?for?example?functions?like?hide,?show,?
all?animation?stuff,?dimensions?getting?and?setting?function?and?a?lot?more.?

Ext.Element?keeps?reference?to?DOM?element?it?is?wrapped?around?in?dom?property.?Once?you?have?an?Ext.Element
?(e.g.?you?call?Ext.get('some-d')?it?is?an?instance?of?Element?class?and?you?can?work?with?it?as?such.?

Now,?imagine?that?you?need?to?hide?1000?DOM?nodes,?you?call?1000?times?Ext.get('some-one-of-
1000-id').hide()?so?you?create?1000?instances?of?Element?just?to?call?one?function:?hide.?

Ext.fly?is?one?instance?of?Ext.Element?with?"replaceable"?DOM?node?it?is?wrapped?around.?
If?you?call?1000?times?Ext.fly('some-one-of-1000-id').hide()?you?1000?times?replace?dom?property?of?one?instance?of?Ext.Element.?

Result:?higher?performance,?lower?memory?usage.?

You?only?need?to?keep?in?mind?that?you?cannot?keep?Element?returned?by?Ext.fly?for?later?use?as?
it's?dom?will?sooner?or?later?gets?replaced?by?another?one.

这段话中,大致的意思如下:

Ext.Element是Ext对Dom元素的一个强有力封装,它封装了很多方便对dom操作的接口(并通过Element的dom属性
引用对应的dom元素),因此每创建一个Element元素都将消耗不少的内存(主要是大量的操作接口消耗),因此如
果创建过多的Element元素必然导致内存占用的剧增和系统性能的下降。

Ext.get和Ext.fly返回的都是一个Element对象,但是Ext.get返回的是一个独立的Element,拥有自己独立的操作接口
封装,可以将其返回值保存到变量中,以便以后调用操作等,这样为重用带来了方便。但是它的一个很大缺
点就是内存消耗问题,假如调用Ext.get(id)1000次,则会在内存中创建1000个独立Element,其内存占用可想而
知。但是很多时候我们可能仅仅只是对该dom元素执行一次很简单的操作,如隐藏(hide),这样如果每次都创建
一个独立Element放在内存中,实在是对内存的巨大浪费,因此当我们在只需要执行一次操作或者一个很简单
的操作时,采用Ext.get就显得很不合理。Ext.fly正是为了解决这个问题而出现,它通过使每次创建的Element共
享内存中的一套操作接口来达到节省内存的效果。

下面来看Ext.fly的实现代码(我简单加了一些注释):

?1 var ?flyFn? = ? function () {} ;? ?2 flyFn.prototype? = ?El.prototype;? ?3 var ?_cls? = ? new ?flyFn();? // 将Element的所有操作接口放在_cls中? ?4 ? ?5 // ?dom?is?optional? ?6 El.Flyweight? = ? function (dom) {? ?7 ???? this .dom? = ?dom;? ?8 } ;? // 仅包含一个dom属性的Object? ?9 ? 10 El.Flyweight.prototype? = ?_cls;? // 将操作接口复制给Element实例对象? 11 El.Flyweight.prototype.isFlyweight? = ? true ;? // 标志该Element是flyweight对象? 12 ? 13 El._flyweights? = ? {} ;? // flyweight对象缓存容器? 14 ? 15 El.fly? = ? function (el,?named) {? 16 ????named? = ?named? || ?'_global';? 17 ????el? = ?Ext.getDom(el);? // 取得dom对象? 18 ???? if ( ! el) {? 19 ???????? return ? null ;? 20 ????} ? 21 ???? if ( ! El._flyweights[named]) {? 22 ????????El._flyweights[named]? = ? new ?El.Flyweight();? // 仅在第一次调用Ext.fly时创建一个Flyweight对象并缓存? 23 ????} ? 24 ????El._flyweights[named].dom? = ?el;? // 将flyweight对象的dom属性指向该el? 25 ???? return ?El._flyweights[named];? 26 } ;
从上面的代码不难看出,仅在第一次调用Ext.fly时创建一个Flyweight对象(该对象包含了Element的所有操作接口)并将其缓存,

之后的所有fly操作都只是修改该flyweight对象的dom属性,每次fly返回的结果都是共享的同一个flyweight对象。
这样每次fly返回的Element相比Ext.get而言,减少了每次创建Element时对大量的操作接口的创建。所有fly的对象
都共享一套Element操作接口,内存占用自然少了很多,而且执行速度也得到了提升。在大量的创建操作中效
果会更加明显。

由于fly的操作原理,我们不能将fly的返回结果保存在变量中以便重用,因为每次fly操作都将可能改变该变量的
dom指向。如下面的代码就是不正确的:

1 var ?my_id? = ?Ext.fly('my_id');???? 2 Ext.fly('another_id');? // 此时my_id的dom引用已经变为another_id???? 3 my_id.highlight('FF0000', {? // 此处的操作将是对??another_id元素的操作??????? 4 ????endColor:'0000FF',?duration:? 3 ???? 5 } );

在以后使用中,一定要合理的利用Ext.get和Ext.fly,避免滥用Ext.get这个“重量级”的方法

  相关解决方案