dom操做中的js优化

频繁地对于DOM进行操做的非常损耗性能,但在富网页应用中咱们编写脚本无可避免地要跟DOM打交道,到底怎么才能优化这个性能瓶颈呢,大体从如下三种状况去考虑: html

访问和修改DOM元素chrome

 

修改DOM样式,会形成页面的重绘和从新排版数组

 

经过DOM事件处理程序来响应用户浏览器

 

访问和修改DOM元素app

  在浏览器中,DOM的实现和Javascript的实现一般是保持相互独立的。下面了解一下主流浏览器的渲染引擎和JS引擎:ide

  浏览器     渲染引擎(内核)     JS引擎  
IE   mshtml.dll(Trident)   JScript
Chrome   WebCore(WebKit)   V8
FireFox   Gecko    Spider-Monkey/TraceMonkey 
Safari   WebCore(WebKit)    JavaScriptCore/SquirrelFish 
 

访问DOM元素的代价就是交一次“桥费”,修改DOM元素则会致使浏览器从新计算页面的几何变化。若是是循环修改DOM元素,其代价可想而知。以下代码:函数

 
function innerHTMLLoop1(){
    for(var count=0;count<10000;count++){
      document.getElementById("test").innerHTML +="增长内容";
    }
}

  在这段代码中,每循环一次都要对DOM元素访问两次:一次是读取innerHTML属性的内容,另外一次是把新的内容写入它。因此一个优化的办法就是使用一个局部变量存储更新后的内容,在循环结束时再一次性写入:oop

function innerHTMLLoop2(){
  var content ="";
   for(var count=0;count<10000;count++){
      content +="增长内容";
    }
   document.getElementById("test").innerHTML += content ;
}
很明显,innerHTMLLoop2交的“桥费”明显要少,由于它只访问了两次DOM元素,一次读入,一次写入。

 

更新页面的两种方法性能比较:innerHTML和DOM方法(如document.creatElment)。性能差异不大,innerHTML好一些,使用简单嘛。另外还有一个更新页面的方法是节点克隆--element.cloneNode()。性能

 

HTML集合的操做优化

HTML集合是用于存放DOM节点引用的类数组对象。可经过下列的方法或属性获得这样的集合:

document.getElementsByName()
document.getElementsByTagName()
document.getElementsByClassName()
document.images 返回对文档中全部 Image 对象引用
document.links  返回对文档中全部 Area 和 Link 对象引用
document.forms 返回对文档中全部 Form 对象引用
document.forms[0].elements 返回对文档中第一个表单的全部元素
 

HTML集合会实时查询文档信息,也就是说当你要用到这个集合时,它会自动查询文档的最新信息。请看以下代码:

 

var allDivs = document.getElementsByTagName("div");   
for(var i=0;i<allDivs.length;i++){
       document.body.appendChild(document.createElement("div"));   
}

例如像上面的那段代码实际上是个死循环,由于每一次访问div集合的length属性,它都会从新计算文档中的div元素数目。这就是html集合低效率的来源。要改进代码就用一个局部变量保存div集合的length属性:
 

for(var i=0, len=allDivs.length; i<len; i++){...}


访问HTML集合的length比数组的length要慢,因此要访问这种集合类的数目length,咱们都应该先用一个局部变量去保存它:
 

var len = 集合.length;

 
另外,访问数组的元素要比访问HTML集合的元素要快。因此咱们能够先把HTML集合转换成数组才去进行相应的操做:
 
//HTML集合转换成数组  
function toArray(coll){
    for(var a=[], i=0, len=coll.legnth; i<len; i++){
      a[i] = coll[i];
    }
    return a;
  }  
//使用  
var coll = document.getElementsByTagName("div");  
var divs = toArray(coll);
 
有人可能会问,这样多用了一个数组副本到底值不值得?这个却是要看状况吧。不过另一种选择,使用局部变量:
function loopColletion(){
    var coll = document.getElmentsByTagName("div");
    var len = coll.length;
    var el = null;
    for(var i = 0; i<len; i++){
      el = coll[i];
      //而后访问局部变量el
    }
  }
 
许多浏览器提供了API函数返回元素节点,这些API都是原生的,因此可用的话就尽可能用。下图列举了一些DOM的属性:

 

上图列举的全部属性能被FF,safari,chrome,opera所支持,ie6-8只支持children。

  遍历children比childNodes更快,由于集合项少了。HTML源码中的空格其实是文本节点,但他们不包含在children中。

另外还有两个比较好的选择器API:document.querySelectorAll()和document.querySelector()。前者接收一个CSS选择器字符串参数并返回一个NodeList类数组对象而不是返回HTML集合,后者只返回符合查询条件的第一个节点。很遗憾IE六、7不支持这两个API。

相关文章
相关标签/搜索