浅谈 Javascript 性能优化
Upcoming SlideShare
Loading in...5
×
 

浅谈 Javascript 性能优化

on

  • 7,678 views

improve javascript performance

improve javascript performance

Statistics

Views

Total Views
7,678
Views on SlideShare
7,639
Embed Views
39

Actions

Likes
16
Downloads
206
Comments
4

3 Embeds 39

http://www.rainoina.com 26
http://www.rainoxu.com 11
http://www.techgig.com 2

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • 精辟、明了,slides也做得漂亮。
    Are you sure you want to
    Your message goes here
    Processing…
  • 温习
    Are you sure you want to
    Your message goes here
    Processing…
  • 收藏。
    Are you sure you want to
    Your message goes here
    Processing…
  • 分享了 哈哈
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

浅谈 Javascript 性能优化 浅谈 Javascript 性能优化 Presentation Transcript

  • 浅谈 JavaScript 性能优化
    龙刚 (@RainoXu)TaobaoUED
    www.rainoxu.com
  • 优化 JavaScript性能,使它运行足够快一个关键因素:运行的时间
  • 响应时间与用户的体验
    0.1s
    用户觉得很流畅
    1.0s
    用户的操作可能偶尔受到影响,并且用户已经能感觉到有些不流畅
    10s
    对用户的影响比较严重,需要相应的进度提示。用户也会有一些沮丧
  • What To Do && How To Do?
  • 管理作用域
    操作数据
    流控制
    Reflow
    DOM操作
    长时间运行的脚本处理
  • 管理作用域
    function add(num1, num2){
    return num1 + num2;
    }
    var result = add(5, 10);
  • 使用局部变量
    局部变量存在于活动对象中,解析器只需查找作用域中的单个对象
    var a = 1;
    function test(){
    //对变量a进行一系列操作
    }
    function test2(){
    var a = 1;
    //对变量a进行一系列操作
    }
  • 另一个例子
    (function(win, S, undefined) {
    ...
    ...
    var doc = win['document'], loc = location,
    EMPTY = '',
    ...
    ...
    })(window, 'KISSY');
  • 数据操作
  • 使用局部变量,它是最快的缓存频繁使用的对象、数组及相关的属性值
  • obj.name比obj.xxx.name访问更快,访问属性的速度,与其在对象中的深度有关
    “ . ”操作的次数直接影响着访问对象属性的耗时
    varobjName = obj.name;
  • KISSY.add('switchable', function(S, undefined) {
    var DOM = S.DOM, Event = S.Event,
    ...
    ...
    });
  • function process(data){
    if (data. count> 0){
    for(vari = 0; i < data.count; i++){
    processData(data.item[i]);
    }
    }
    }
  • function process(data){
    var count = data.count;
    if (count > 0){
    for(vari = 0; i < count ; i++){
    processData(data.item[i]);
    }
    }
    }
  • NodeList
    不直接操作NodeList,将其转换成静态数组后再使用
    方法:
    Array.prototype.slice.call() => 标准浏览器
    逐个拷贝到一个新数组中 => For IE
  • 大部分JS库都有提供将Array-Like的对象转变成Array的方法(如KISSY提供的makeArray()方法);部分JS库在返回元素集合时,已预处理成Array(例子:YUI的DOM相关操作方法)
  • 遍历NodeList时,不做对当前NodeList相关结构有影响的DOM操作,并且如之前所提到的,要缓存一些频繁使用到的属性值,以避免杯具发生。
  • vardivs = document.getElementsByTagName('DIV');
    //假定页面中有div,所以divs.length是大于0的
    for (varidx = 0; idx < divs.length; idx++){
    document.body.appendChild(
    //杯具悄然而置
    document.createElement('DIV')
    );
    console.info(divs.length);
    }
  • 杯具的原因?
    通过getElementsByTagName()获取得到的是一个LiveNodeList的引用,任何对其相关的DOM操作都会立即反应在这个NodeList上面
    通过不断地往document.body下插入div 节点,for循环的终止条件(div.length也随之改变)失效,陷入死循环。
  • Live NodeListvs Static NodeList
    理论上,静态的东西应该是最快的,但是实际情况是,Live NodeList更快。
  • Live NodeListvs Static NodeList
    原因:目前市场上的浏览器,对Live NodeList做了缓存
  • Live NodeListvs Static NodeList
    结论:优先使用Live NodeList,通过选择器获取以后,再进一步转换成数组来使用。这也是目前许多JS库在使用的方案。
  • DOM操作
    指明操作DOM的context
    YUI:
    Array getElementsByClassName ( className , tag , root , apply , o , overrides )
    KISSY:
    Array<HTMLElement> query ( selector, context )
    即便是用原生的JS,也应该指明:
    context.getElementsByTagName()
  • DOM操作
    增删、修改节点
    使用DocumentFragment
    使用cloneNode()复制一份目标节点来处理
    如果是直接修改DOM,请先将其display:none;
  • 一个方法尽可能只做一件事
    拆分功能,让一个方法只做一件事,通过不断地调用方法来实现复杂功能,但是,这些简单方法要避免相互交叉调用。
  • KISSY Poster中的一些方法拆分
  • KISSY Poster中的一些方法拆分
  • Be Lazy
    使脚本尽可能少地运行,或者不运行。
  • 短路表达式应用:如 a && b || c
    基于事件去写相应的处理方法
    惰性函数
  • 合理地使用事件代理
    DOM与事件处理
  • 为元素绑定事件
    Event.on ( target, type, fn, scope )
  • 事件代理的原理
    冒泡
    捕获
  • 事件代理应用的场景?
  • Event.on(container, ‘click’, function (ev){
    var target = ev.target();
    switch(target.className){//或者可以是nodeName
    ...
    ...
    ...
    }
    });
  • 流控制
  • if(...){
    }elseif(...){
    }elseif(...){
    }elseif(...){
    }elseif(...){
    }elseif(...){
    }else{
    }
  • 在if语句中,将经常会发生的条件,放在靠上的位置
    if的条件为连续的区间时,可以使用二分法的方式来拆分
    较多离散值的判断,可以使用switch来替代
    使用数组查询的方式
  • 要注意隐式的类型转换
    varfoo = 0;
    if(foo == false){
    ...
    }
  • 小心递归!
  • function recurse(){
    recurse();
    }
    recurse();//又是一个杯具
  • 浏览器对调用栈的最大限度的定义各不一样
    递归的相互调用、自身调用可能触发浏览器的调用栈的最大极限
  • Reflow
  • 主要引起Reflow的因素
    操作DOM树
    与布局有关的样式改变
    改变className
    窗口大小调整
    字休大小
  • 优化运行时间较长的脚本
  • 原因:
    大量DOM操作
    过多的循环与递归
    解决问题的最佳实践:
    使用定时器
  • 最后,优化原则?
  • 2/8原则
    考虑大多数情况,极端情况,有能力则兼顾之,适当取舍
  • 性能与可维护性权衡之一原则
  • 站在巨人的肩膀上,看得更远
    YAHOO的前端小组、JohnResig、NicholasC.Zakas等都已经总结了很多有用的性能优化方面的经验,以他们的研究成果做为优化时的参考。
  • 好的编程习惯
    • 不以善小而不为
    • 思先于行,不必过早优化
  • 最后,感谢玉伯、云谦、圆心、龙俊、释然对我此次的分享提供了许多帮助和建议。
  • Question?