Onelong

分享知识,与你一起进步......
RSS icon Home icon
  • 分享:Javascript优化

    post by onelong / 2010-11-4 2:09 Thursday [javascript]

    为什么要进行Javascript优化呢?

    优化 JavaScript 性能,使它运行足够快,也就是运行的时间。响应时间当时越短越好啦,但是影响用户体验的响应时间极限那个呢?

    响应时间与用户的体验

    0.1s:用户觉得很流畅

    1.0s:用户的操作可能偶尔受到影响,并且用户已经能感觉到有些不流畅

    10s:对用户的影响比较严重,需要相应的进度提示。用户也会有一些沮丧

    所以我们设计程序的响应最后是控制在1s内!当然这是无法做到最快的无奈选择了!

    看了以上前言!那么怎样优化javascript的性能呢?

    1.         管理作用域

    2.         操作数据

    3.         流控制

    4.         Reflow

    5.         DOM操作

    6.         长时间运行的脚本处理

    以上是被人分享的经验!具体怎样做呢!看下面的例子吧!

    管理作用域

    function add(num1, num2){

             return num1 + num2;

    }

    var result = add(5, 10);

    点击查看原图

    使用局部变量

    局部变量存在于活动对象中,解析器只需查找作用域中的单个对象

     

    var a = 1;

    function test(){

             //对变量a进行一系列操作

    }

     

    function test2(){

             var a = 1;

              //对变量a进行一系列操作

    }

    2

    (function(win, S, undefined) {

             ...

             ...

        var doc = win['document'], loc = location,

            EMPTY = '',

             ...

             ...

    })(window, 'KISSY');

    Doc这个局部变量,在此匿名函数在执行时,作为活动对象的一个属性,位于作用域链的顶端,查询这个变量,速度就比较快了

     

    数据操作

    使用局部变量,它是最快的
    缓存频繁使用的对象、数组及相关的属性值

    obj.nameobj.xxx.name访问更快,访问属性的速度,与其在对象中的深度有关

    . ”操作的次数直接影响着访问对象属性的耗时

    var objName = obj.name;

     

    比较下面的代码:

    function process(data){

             if (data. count> 0){

                       for(var i = 0; i < data.count; i++){

                                processData(data.item[i]);

                       }                

             }

    }

     

     

    function process(data){

             var count = data.count;

             if (count > 0){

                       for(var i = 0; i < count ; i++){

                                processData(data.item[i]);

                       }                

             }

    }

    那个比较好呢? 显然是后面吧,减少数据操作!

    NodeList

    不直接操作NodeList,将其转换成静态数组后再使用

     

    方法:

    Array.prototype.slice.call() => 标准浏览器

    逐个拷贝到一个新数组中 => For IE

    大部分JS库都有提供将Array-Like的对象转变成Array的方法(如KISSY提供的makeArray()方法);部分JS库在返回元素集合时,已预处理成Array(例子:YUIDOM相关操作方法)

    遍历NodeList时,不做对当前NodeList相关结构有影响的DOM操作,并且如之前所提到的,要缓存一些频繁使用到的属性值,以避免杯具发生。

     

    var divs = document.getElementsByTagName('DIV');

            

             //假定页面中有div,所以divs.length是大于0

             for (var idx = 0; idx < divs.length; idx++){

                       document.body.appendChild(

                                //杯具悄然而置

                                document.createElement('DIV')

                       );

                       console.info(divs.length);

             }

    通过getElementsByTagName()获取得到的是一个Live NodeList的引用,任何对其相关的DOM操作都会立即反应在这个NodeList上面

             通过不断地往document.body下插入div 节点,for循环的终止条件( div.length也随之改变)失效,陷入死循环。

    理论上,静态的东西应该是最快的,但是实际情况是,Live NodeList更快。

    原因:目前市场上的浏览器,对Live NodeList做了缓存

    优先使用Live NodeList,通过选择器获取以后,再进一步转换成数组来使用。这也是目前许多JS库在使用的方案

     

    DOM操作

    指明操作DOMcontext

    YUI:

             Array getElementsByClassName ( className , tag , root , apply , o , overrides )

     

    KISSY:

             Array<HTMLElement> query ( selector, context )

     

    即便是用原生的JS,也应该指明:

             context.getElementsByTagName()

     

    增删、修改节点

    使用DocumentFragment

    使用cloneNode()复制一份目标节点来处理

    如果是直接修改DOM,请先将其display:none

     

    流控制

    if(...){

    }elseif(...){

    }elseif(...){

    }elseif(...){

    }elseif(...){

    }elseif(...){

    }else{

    }

    if语句中,将经常会发生的条件,放在靠上的位置

    if的条件为连续的区间时,可以使用二分法的方式来拆分

    较多离散值的判断,可以使用switch来替代使用数组查询的方式

     

    主要引起Reflow的因素

    操作DOM

    与布局有关的样式改变

    改变className

    窗口大小调整

    字休大小

    分享别人的经验!!

    标签: javascript 优化
    引用地址:
     

    评论:

    1. Melanie
      Nice to read your blog

    我要评论