Javascript性能优化(一)

 

一、加载

 

1. 依据HTML 4规范,script标签可以放置在head和body标签中的任意位置

2. 下载js脚本会阻塞其他页面文件下载,所以应尽可能将script标签放置在body底部

3. HTML 4为script标签增加了一个defer属性,表明延迟执行,但这并不是标准做法

4. 将多个script合并后压缩,放置在body标签底部,是引入多个外链javascript文件的最佳实践

5. 通过动态创建标签,可以异步引入js文件,代码如下:

 1 function loadScript(url, callback) {
 2     
 3     var script = document.createElement(‘script‘)
 4     script.type = ‘text/javascript‘
 5 
 6     // IE
 7     if (script.readyState) {    
 8         script.onreadystatechange = function() {
 9             if (script.readyState == ‘loaded‘ || script.readyState == ‘complete‘) {
10                 script.onreadystatechange = null
11                 callback()
12             }
13         }
14 
15     // other browser
16     } else {
17         script.onload = function() {
18             callback()
19         }
20     }
21 
22     script.src = url
23     document.getElementByTagName(‘head‘)[0].appendChild(script)
24 }

6.使用xhr对象,同样可以异步引入js。与上面不同的是,你可以获得准确的加载进度,并且,脚本并不是一下载好就执行(取决于script标签添加到页面中的时间)

 1 var xhr = new XMLHttpRequest()
 2 
 3 xhr.open(‘get‘, ‘file.js‘, true)
 4 xhr.onreadystatechange = function() {
 5 
 6     if (xhr.readyState == 4) {
 7         if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
 8 
 9             var script = document.createElement(‘script‘)
10 
11             script.type = ‘text/javascript‘
12             script.text = xhr.responseText
13 
14             document.body.appendChild(script)
15         }
16     }
17 }

 

 

二、数据

 

1. javascript数据类型:直接量、变量、数组、对象

2. 直接量和局部变量的访问速度优于数组项和对象成员,变量访问性能与作用域嵌套有直接关系

3. 闭包比非闭包函数需要更多内存开销(变量的生命周期延长,并且最后不一定能释放)

4. 使用hasOwnProperty只对实例进行查找,而使用for in遍历对象成员可以访问prototype

5. 每次使用 "." 操作符时,会导致javascript引擎搜索所有对象成员,对象成员嵌套越深,速度越慢。尤其是当访问的属性(方法)在原型链中时

6. 使用 "." 操作符,在safari下会比[key]更快,但[key]的写法更通用(属性为保留字)

7. 命名空间是导致频繁访问嵌套属性的起因之一,对命名空间进行缓存,可以有效减少对象访问次数

  

1 // 对命名空间进行缓存
2 var load = ME.core.load
3 
4 // 对resource.length进行缓存,避免每次遍历都访问resource
5 for (var i = 0, length = resource.length; i < length; i++) {
6 
7     load.LoadResource(resource[i].url)
8 }

 

 

三、DOM

 

1. 文档对象模型(DOM)是一个语言无关的,用于操作XML和HTML文档的应用程序接口

2. DOM和ECMAScript是两个独立的功能,当他们通过接口相互访问,就会产生消耗。访问DOM元素要被收取“过桥费”,修改元素则更为昂贵,因为它会导致浏览器重新计算页面的几何变化

3. 使用dom方式生成html(body.appendChild)与使用innerHTML效率大致相同,在旧版本浏览器上innerHTML更胜一筹

4. 在大多数浏览器上,克隆节点(cloneNode)比生成节点(createElement)更有效率

5. HTML集合一直与文档保持着链接,每次访问时,都会重复执行查询的过程,哪怕只是获取集合里的元素个数。以下方法和属性会造成这种低效率情况

1 document.getElementsByName()
2 document.getElementsByClassName()
3 document.getElementsByTagName()
4 
5 document.images
6 document.forms
7 document.links
8 document.forms[0].elements

6. 遍历元素子节点,ie下使用nextSibling比childNodes更快

 1 // nextSibling
 2 function testNextSibling() {
 3     var el = document.getElementById(‘father‘),
 4         ch = el.firstChild,
 5         name = ‘‘
 6 
 7     do {
 8         name = ch.nodeName
 9 
10     } while(ch = ch.nextSibling)
11 
12     return name
13 }
14 
15 // childNodes
16 function testChildNodes() {
17     var el = document.getElementById(‘father‘),
18         ch = el.childNodes,
19         len = ch.length,
20         name = ‘‘
21 
22     for (var i = 0; i < len; i++) {
23         name = ch[i].nodeName
24     }
25 
26     return name
27 }

7. 使用原生的querySelector和querySelectorAll将比遍历获得更好的效率(ie8+)

8. 当DOM的变化影响了几何属性(盒模型),其他元素的几何属性和位置也会因此受到影响(normal flow)。浏览器会使渲染树种受到影响的部分失效,并重新构造渲染树。这个过程称为“重排”。完成重排后,浏览器会重新绘制受到影响的部分到屏幕中,这个过程称为“重绘”。以下情况会发生重排:

  • 添加或删除可见的DOM元素
  • 元素位置改变
  • 元素盒模型改变(padding、margin、width、height、border)
  • 内容改变,如文字或图片路径
  • 页面渲染器初始化
  • 浏览器窗口尺寸改变

  有些改动会触发整个页面的重排,例如,当滚动条出现时

9. 重排会产生计算消耗,多数浏览器会通过队列化修改并批量执行来优化重排过程。获取布局信息的操作会导致列队刷新,比如以下方法:

  • offsetTop,offsetLeft,offsetWidth,offsetHeight
  • scrollTop,scrollLeft,scrollWidth,scrollHeight
  • clientTop,clientLeft,clientWidth,clientHeight
  • getComputedStyle()

  在修改样式的过程中最好避免使用上述属性

10. 将多次改动合并为一次,可以大幅提高效率。另一种一次性修改样式的方式是修改class属性,这种方法更利于维护和复用,虽然可能带来轻微性能影响(改变类时需要检查级联样式)

11. 有三个方法可以使DOM脱离文档流

  • 隐藏元素,应用修改,重新显示
  • 使用文档片段,在当前DOM树外构建一个子树,再拷贝回文档
  • 将原始元素拷贝到一个脱离文档的节点中,修改副本,再替换原始元素

12. 在IE 7-8上大范围使用hover会降低响应速度

13. 通过事件委托可以减少事件的绑定数量,从而提升效率。通过子元素冒泡触发父元素的事件,可能更加简单和优雅

14. 将需要大量修改的DOM节点(动画元素)设置为绝对定位,使其脱离文档流以减少影响

 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。