53
浅浅 JavaScript 浅浅浅浅 浅浅 @RainoXu TaobaoUED www.rainoxu.com

浅谈 Javascript 性能优化

  • Upload
    rainoxu

  • View
    7.680

  • Download
    3

Embed Size (px)

DESCRIPTION

improve javascript performance

Citation preview

Page 1: 浅谈 Javascript 性能优化

浅谈 JavaScript 性能优化

龙刚 ( @RainoXu ) TaobaoUEDwww.rainoxu.com

Page 2: 浅谈 Javascript 性能优化

优化 JavaScript 性能,使它运行足够快一个关键因素:运行的时间

Page 3: 浅谈 Javascript 性能优化

响应时间与用户的体验• 0.1s– 用户觉得很流畅

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

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

Page 4: 浅谈 Javascript 性能优化

What To Do && How To Do?

Page 5: 浅谈 Javascript 性能优化

• 管理作用域• 操作数据• 流控制• Reflow• DOM 操作• 长时间运行的脚本处理

Page 6: 浅谈 Javascript 性能优化

管理作用域function add(num1, num2){

return num1 + num2; } var result = add(5, 10);

Page 7: 浅谈 Javascript 性能优化

使用局部变量局部变量存在于活动对象中,解析器只需查找作用域中的单个对象var a = 1;function test(){

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

function test2(){var a = 1; // 对变量a进行一系列操作

}

Page 8: 浅谈 Javascript 性能优化

另一个例子(function(win, S, undefined) {

...

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

...

...})(window, 'KISSY');

Page 9: 浅谈 Javascript 性能优化

数据操作

Page 10: 浅谈 Javascript 性能优化

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

Page 11: 浅谈 Javascript 性能优化

obj.name 比 obj.xxx.name 访问更快,访问属性的速度,与其在对象中的深度有关“ . ” 操作的次数直接影响着访问对象属性的耗时var objName = obj.name;

Page 12: 浅谈 Javascript 性能优化

KISSY.add('switchable', function(S, undefined) { var DOM = S.DOM, Event = S.Event,

...

...});

Page 13: 浅谈 Javascript 性能优化

function process(data){if (data. count> 0){

for(var i = 0; i < data.count; i++){processData(data.item[i]);

}}

}

Page 14: 浅谈 Javascript 性能优化

function process(data){var count = data.count;if (count > 0){for(var i = 0; i < count ; i++){processData(data.item[i]);}}

}

Page 15: 浅谈 Javascript 性能优化

NodeList

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

Array.prototype.slice.call() => 标准浏览器逐个拷贝到一个新数组中 => For IE

Page 16: 浅谈 Javascript 性能优化

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

Page 17: 浅谈 Javascript 性能优化

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

Page 18: 浅谈 Javascript 性能优化

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);

}

Page 19: 浅谈 Javascript 性能优化

杯具的原因?通过 getElementsByTagName() 获取得到的是一个 Live NodeList 的引用,任何对其相关的 DOM 操作都会立即反应在这个NodeList 上面通过不断地往 document.body 下插入 div 节点, for 循环的终止条件( div.length 也随之改变)失效,陷入死循环。

Page 20: 浅谈 Javascript 性能优化

Live NodeList vs Static NodeList

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

Page 21: 浅谈 Javascript 性能优化

Live NodeList vs Static NodeList

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

Page 22: 浅谈 Javascript 性能优化

Live NodeList vs Static NodeList

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

Page 23: 浅谈 Javascript 性能优化

DOM 操作• 指明操作 DOM 的 context

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

KISSY:Array<HTMLElement> query ( selector, context )

即便是用原生的 JS ,也应该指明 :context.getElementsByTagName()

Page 24: 浅谈 Javascript 性能优化

DOM 操作• 增删、修改节点– 使用 DocumentFragment– 使用 cloneNode() 复制一份目标节点来处理– 如果是直接修改 DOM ,请先将其 display:none;

Page 25: 浅谈 Javascript 性能优化

一个方法尽可能只做一件事拆分功能,让一个方法只做一件事,通过不断地调用方法来实现复杂功能,但是,这些简单方法要避免相互交叉调用。

Page 26: 浅谈 Javascript 性能优化

KISSY Poster 中的一些方法拆分

Page 27: 浅谈 Javascript 性能优化

KISSY Poster 中的一些方法拆分

Page 28: 浅谈 Javascript 性能优化

Be Lazy使脚本尽可能少地运行,或者不运行。

Page 29: 浅谈 Javascript 性能优化

短路表达式应用:如 a && b || c

基于事件去写相应的处理方法惰性函数

Page 30: 浅谈 Javascript 性能优化

• 合理地使用事件代理DOM 与事件处理

Page 31: 浅谈 Javascript 性能优化

为元素绑定事件Event.on ( target, type, fn, scope )

Page 32: 浅谈 Javascript 性能优化

事件代理的原理冒泡 捕获

Page 33: 浅谈 Javascript 性能优化

事件代理应用的场景?

Page 34: 浅谈 Javascript 性能优化
Page 35: 浅谈 Javascript 性能优化

Event.on(container, ‘click’, function (ev){var target = ev.target();

switch(target.className){//或者可以是 nodeName.........}

});

Page 36: 浅谈 Javascript 性能优化

流控制

Page 37: 浅谈 Javascript 性能优化

if(...){}elseif(...){}elseif(...){}elseif(...){}elseif(...){}elseif(...){}else{}

Page 38: 浅谈 Javascript 性能优化

在 if语句中,将经常会发生的条件,放在靠上的位置if 的条件为连续的区间时,可以使用二分法的方式来拆分较多离散值的判断,可以使用 switch 来替代使用数组查询的方式

Page 39: 浅谈 Javascript 性能优化

要注意隐式的类型转换var foo = 0;if(foo == false){

...}

Page 40: 浅谈 Javascript 性能优化

小心递归!

Page 41: 浅谈 Javascript 性能优化

function recurse(){recurse();

}recurse(); //又是一个杯具

Page 42: 浅谈 Javascript 性能优化

• 浏览器对调用栈的最大限度的定义各不一样• 递归的相互调用、自身调用可能触发浏览器的调用栈的最大极限

Page 43: 浅谈 Javascript 性能优化

Reflow

Page 44: 浅谈 Javascript 性能优化

主要引起 Reflow 的因素• 操作 DOM树• 与布局有关的样式改变• 改变 className• 窗口大小调整• 字休大小

Page 45: 浅谈 Javascript 性能优化

优化运行时间较长的脚本

Page 46: 浅谈 Javascript 性能优化

• 原因:– 大量 DOM 操作– 过多的循环与递归

• 解决问题的最佳实践:– 使用定时器

Page 47: 浅谈 Javascript 性能优化

最后,优化原则?

Page 48: 浅谈 Javascript 性能优化

考虑大多数情况,极端情况,有能力则兼顾之,适当取舍2/8 原则

Page 49: 浅谈 Javascript 性能优化

性能与可维护性权衡之一原则

Page 50: 浅谈 Javascript 性能优化

YAHOO 的前端小组、 John Resig 、 Nicholas C.Zakas等都已经总结了很多有用的性能优化方面的经验,以他们的研究成果做为优化时的参考。

站在巨人的肩膀上,看得更远

Page 51: 浅谈 Javascript 性能优化

• 不以善小而不为• 思先于行,不必过早优化好的编程习惯

Page 52: 浅谈 Javascript 性能优化

最后,感谢玉伯、云谦、圆心、龙俊、释然对我此次的分享提供了许多帮助和建议。

Page 53: 浅谈 Javascript 性能优化

Question?