首页 > 代码库 > DOM编程的性能问题

DOM编程的性能问题

  

  用脚本进行DOM操作的代价很昂贵,它是富Web应用中最常见的性能瓶颈。

 

浏览器中的DOM:天生就慢

  DOM(文档对象模型)是独立于语言的,但在浏览器中的接口是用JavaScript实现的。两个相互独立的功能只要通过接口彼此连接,就会产生消耗。

  访问DOM元素是有代价的,修改元素则更甚。

1 function innerHTMLLoop(){
2     for(var count = 0; count < 15000; count++){
3         document.getElementById(‘here‘).innerHTML += ‘a‘;//糟糕透顶,难道要重复15000次 访问+重写 吗?
4     }
5 }

  减少访问DOM的次数,把运算留在ECMAScript这一端处理

1 function innerHTMLLoop(){
2     var content = ‘‘;
3     for(var count = 0; count < 15000; count++){
4         content += ‘a‘;
5     }
6     document.getElementById(‘here‘).innerHTML += content;//一次 访问+重写,比起上面,简直好太多
7 }

 

 

昂贵的集合

  document.getElementsByTagName()

  document.getElementsByClassName()

  document.images

  document.links

  document.forms

  以上方法和属性的返回值为HTML集合对象,类似数组(不是数组,没有push slice等方法),提供了length属性,可以以数字索引访问其中的元素

  重点是,HTML集合对象以一种『假定实时态』实时存在,一直与文档保持着连接,当底层文档对象更新时,它也会更新。这就是低效之源。

  

1 var alldivs = document.getElementsByTagName(‘div‘);
2 for(var i = 0; i < alldivs.length; i++){              //length一直在变,一个意外的死循环
3     document.body.appendChild(document.createElement(‘div‘));
4 }
  • 将集合拷贝至数组,访问数组较快(但这也会因为额外的步骤多遍历一次集合,评估而定)
  • 缓存length属性
  • 多次访问同一个集合元素时使用局部变量缓存

 

 

只取得元素节点

只取得元素节点 不建议使用
children childNodes
childElementcount

childNodes.length

firstElementChild

firstChild

lastElementChild lastChild
nextElementSibling nextSibling
priviousElementSibling priviousSibling

 

选择器API

  querySelectorAll()

  使用CSS选择器作为参数,返回Nodelist类数组对象,不会返回HTML集合,因此避免了HTML集合引起的性能(和潜在逻辑)问题

1 var elements1 = document.getElementById(‘menu‘).getElementsByTagName(‘a‘);//id为menu的下面的所有<a>
2 var elements2 = document.querySelectorAll(‘#menu a‘);//同上,对比之下,querySeletorAll较简洁
3 
4 var errs = document.querySelectorAll(‘div.warning, div.notice‘);//类为warning和notice的<div>

 

 

 

高性能JavaScript P35-50

DOM编程的性能问题