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

浅谈 Javascript 性能优化

Aug 26, 2014

Download

Self Improvement

rainoxu

improve javascript performance
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
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?