频繁地对于DOM进行操作的很是损耗性能,但在富网页应用中我们编写脚本无可避免地要跟DOM打交道,到底怎么才能优化这个性能瓶颈呢,大致从以下三种情况去考虑:

访问和修改DOM元素

修改DOM样式,会造成页面的重绘和重新排版

通过DOM事件处理程序来响应用户

 

访问和修改DOM元素

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

  浏览器     渲染引擎(内核)     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属性的内容,另一次是把新的内容写入它。所以一个优化的办法就是使用一个局部变量存储更新后的内容,在循环结束时再一次性写入:

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集合,后者只返回符合查询条件的第一个节点。很遗憾IE6、7不支持这两个API。

dom操作中的js优化的更多相关文章

  1. js优化原则

    首先,与其他语言不同,JS的效率很大程度是取决于JS engine的效率.除了引擎实现的优劣外,引擎自己也会为一些特殊的代码模式采取一些优化的策略.例如FF.Opera和Safari的JS引擎,都对字 ...

  2. 从字符串拼接看JS优化原则

    来自知乎的问题:JavaScript 怎样高效拼接字符串? 请把以下用于连接字符串的JavaScript代码修改为更高效的方式: var htmlString ='< div class=”co ...

  3. 前端js优化方案(连续更新)

    最近在读<高性能javascript>,在这里记录一下读后的一些感受,顺便加上自己的一些理解,如果有兴趣的话可以关注的我的博客http://www.bloggeng.com/,我会不定期发 ...

  4. js优化 前端小白适用

    注意啦,前端初学者适合看的js优化,当你看我的优化认为太low,那么恭喜,你已经脱离初学者了. 首先这边我觉得分享的还是以js为主,前端性能优化,我认为最重要的还是js,因为js是一门解释型的语言,相 ...

  5. 前端js优化方案(一)

    最近在读<高性能javascript>,在这里记录一下读后的一些感受,顺便加上自己的一些理解,如果有兴趣的话可以关注的我的博客http://www.bloggeng.com/,我会不定期发 ...

  6. DOM操作的性能优化

    DOM操作的真正问题在于 每次操作都会出发布局的改变.DOM树的修改和渲染. React解决了大面积的DOM操作的性能问题,实现了一个虚拟DOM,即virtual DOM,这个我们一条条讲. 所以关于 ...

  7. JavaScript性能优化篇js优化

    JavaScript性能优化篇js优化   随着Ajax越来越普遍,Ajax引用的规模越来越大,Javascript代码的性能越来越显得重要,我想这就是一个很典型的例子,上面那段代码因为会被频繁使用, ...

  8. require.js优化器

    项目发布前,require.js优化器可以合并require.js各个模块. 官网: http://requirejs.org/docs/optimization.html 安装 npm instal ...

  9. 关于js优化和css优化

    css优化: 1.css代码的压缩. 2.css文件的合并. 3.不滥用float,因为float在渲染时计算量比较大,所以尽量减少使用float. 4.避免在html标签中写style属性. js优 ...

随机推荐

  1. oracle查看字符集后修改oracle服务端和客户端字符集的步骤

    1.oracle server端字符集查询代码如下:select userenv ('language')  from dual; server字符集修改: 将数据库启动到RESTRICTED模式下做 ...

  2. 手机web开发Repeater四层嵌套

    最近有朋友想让我给他做个手机上页面,页面功能是显示省--市--区--门店信息,这种层级关系的数据,首先来看看效果: 我想现在的手机都是智能机了对于普通的asp.net页面开发应该没什么两样,不过最终开 ...

  3. python基于http协议编程:httplib,urllib和urllib2<转>

    httplib实现了HTTP和HTTPS的客户端协议,一般不直接使用,在python更高层的封装模块中(urllib,urllib2)使用了它的http实现. httplib.HTTPConnecti ...

  4. $(document).ready()使用讨论

    <script language="JavaScript" type="text/javascript"> $(document).ready(fu ...

  5. iframe自适应高度的多种方法小结

    转自:http://www.jb51.net/article/15780.htm 不带边框的iframe因为能和网页无缝的结合从而不刷新页面的情况下更新页面的部分数据成为可能,可是 iframe的大小 ...

  6. iOS xcode8提交 iOS10 “此构建版本无效” (已解决)

    近期上传应用,遇到了"此构建版本无效"的问题,如图 网查了一下,解决了这个问题:(注意:先不要急着怀疑是网络问题,重新提交,先检查问题,别问我怎么知道的...) 1:iOS10 之 ...

  7. iOS开发——数据持久化Swift篇&(一)NSUserDefault

    NSUserDefault //******************** 5.1 NSUserDefault和对象归档 func useNSUserDefault() { //通过单利来创建一个NSU ...

  8. io cache

    http://blog.163.com/digoal@126/blog/static/163877040201571511020418 http://dirlt.com/

  9. leetcode二分查找问题整理

    自从做完leetcode上的三道关于二分查找的题后,我觉得它是比链表找环还恶心的题,首先能写出bugfree代码的人就不多,而且可以有各种变形,适合面试的时候不断挑战面试者,一个程序猿写代码解决问题的 ...

  10. 深入解析 ext2 文件系统

     很久以来,就想写一篇关于ext 家族文件系统的文章,源于我刚工作的时候,曾经一不小心rm -rf,误删除了很多文件,当时真想有个数据恢复软件能帮我把数据回复了.当然学习数据恢复,首先要学习文件系统. ...