javascript 文件加载速度
- 延迟加载JavaScript文件,把script引用放在body底部,让页面其他元素先解析 - 放在head中文件夹在会阻塞页面元素渲染
- 使用成熟框架按需加载(异步)- headjs, requirejs, labjs
良好的编码习惯
- 缓存计算结果 - 如果计算耗时且计算结果不会改变
- 少用for-in循环(性能差) - 改用for循环
- 谨慎使用eval
- 数组应保存单一类型的数据
- 正确使用内存回收
- 不使用delete销毁- 影响浏览器引擎优化
- 遵从浏览器回收垃圾的原则编写对象
- 尽量不使用全局变量 -全局变量再页面的整个生命周期不会被回收
- 确保解除已经不需要的事件监听, 如那些要移出的dom对象上绑定的事件
- 不要在闭包中返回外部不需要的对象
使用高性能的变量或属性值读取方式
tip
- 作用域: 变量或函数的作用范围
- JavaScript没有块级作用域(与c# java不同)- 大括号不会形成单独作用域
- 最大作用域,全局作用域
- 最小作用域是函数 - 函数内定义的变量,函数 只能在函数内部使用, 可以使用外部函数的变量或者函数
- 因为函数嵌套定义,会形成作用域包含关系 - 作用域链。
- 函数被调用时,作用域链被出示化
- 使用变量时,会顺着作用域链从底向高层查找,知道找到变量的定义或者没找到,定义为undefined
- 如果频繁调用外层作用域的变量会影响性能- 如果函数内部多次调用外层作用域的变量,可以先把变量缓存起来。
- 对象原型链上检索对象属性或方法会影响性能(与作用域类似)
- 把属性值缓存在局部变量中,提高读取对象的性能
高效的DOM操作
浏览器渲染的原理
1. 浏览器解析HTML文档构建DOM树
2. 浏览器解析CSS产生CSS规则树
3. JavaScript代码可能会修改生成的dom树和css规则树
4. 浏览器根据dom树和css规则树构建渲染树
- css根据选择器匹配html元素
- 渲染树包括,元素的大小,边距,等样式。
- 渲染树不包含隐藏元素以head等不可见元素
5. 浏览器根据元素的坐标和大小来计算每个元素的位置,绘制这些元素到页面上
dom操作性能损耗最大的两个因素
- 浏览器重绘(repaint): 页面某些部分重新绘制,颜色,背景色的修改 但元素位置和尺寸没有改变
- 重排(reflow):元素的位置或尺寸发生了改变,浏览器需要重新技术渲染树,会导致渲染树一部分或全部发生变化
- 重排的性能更低
导致重绘或重排的dom操作
- 增删改dom元素
- 页面初始化的渲染
- 移动dom元素
- 修改css,改变元素尺寸
- 元素内容改变,撑大尺寸
- 浏览器尺寸改变
- 浏览器窗口滚动
最佳实践
1. 合并多次的dom操作为单次dom操作
2. 把dom元素离线或隐藏后修改 - 对脱离了页面布局留的dom元素的操作不会导致性能问题
1. 使用文档片段
var fragment = document.createDocumentFragment();
//大量基于fragment 的dom操作
document.getElementById('').appendChild(fragment);
2. 通过设置dom元素的display样式为none来隐藏元素
var myElement = document.getElementById('');
myElement.style.display = 'none';
//基于myElement的dom操作
//...
myElement.style.display = 'block';
3. 克隆DOM元素到内存中