美文网首页
innerHTML与DOM操作性能比较

innerHTML与DOM操作性能比较

作者: 陈学谦_ | 来源:发表于2017-04-28 12:39 被阅读400次

    一、故事背景

    这周一看《高程3》中,“11.3.6 插入标记”章节中的第4部分,“内存与性能”,里面有谈到关于innerHTML的性能问题。

    一般来说,在插入大量新HTML标记时,使用innerHTML属性与通过多次DOM操作先创建节点再指定它们之间的关系相比,效率要高得多。这是因为在设置innerHTML或outerHTML时,就会创建一个HTML解析器。这个解析器是在浏览器级别的代码(通常是C++编写的)基础上运行的,因此执行JavaScript快得多。

    我记得我原来在看《DOM启蒙》的时候,书上有说过关于innerHTML的问题,说它很耗性能,尽量避免使用它。当时我也没去求证,并且以为作者的意思是“innerHTML性能很差”,并且还将这个“经验”传授给了我的同学(当然在这次实验过后我告诉了他我之前说的有误)。于是我再次翻开这本书,在书中1.8章节,最后的“注意”中的第3条:

    innerHTML调用了一个沉重且高消耗的HTML解析器,而文本节点生成几乎不足为虑;因此省着点用innerHTML和它的小伙伴们。

    其实书中说的也没错,是我当时理解错了。innerHTML是很耗能,但是并不代表其执行速度慢比DOM操作慢,况且作者只是将innerHTML和创建文本节点做对比。

    二、添加节点实验

    1. 计时器

    首先我们需要一个计时器:

    /**
     * 获取当前时间,毫秒为单位
     */
    function getTime() {
      // 如果浏览器不支持window.performance,就用Date.now()获取当前时间
      return window.performance ? window.performance.now() :  Date.now();
    }
    

    2. 一些需要用到的变量

    var div = document.querySelector('div');
    var iHtml = ""; // innerHTML这种的字符串
    var startTime;
    var elNum = 10000; // 每次添加节点的个数
    

    3. 通过innerHTML添加节点

    startTime = getTime(); // 开始计时
    for (var i = 0; i < elNum; i += 1) {
      iHtml += "<p>Hello World</p>";
      // 别这么写:
      // div.innerHTML += "<p>Hello World</p>";
      // 因为这样每次循环都有两个操作:
      // 1. 清空之前的innerHTML  2. 赋上新的innerHTML
    }
    div.innerHTML = iHtml;
    console.log(getTime() - startTime); // 输出耗时
    

    3. 通过DOM操作添加节点

    startTime = getTime(); // 再次计时
    for (var i = 0; i < elNum; i += 1) {
      var p = document.createElement('p');
      p.appendChild(document.createTextNode('Hello World'));
      div.appendChild(p);
    }
    console.log(getTime() - startTime); // 输出耗时
    

    4. 输出结果

    你会发现:

    唉????

    但你再刷新试试

    唉????

    你会发现真的很神奇,到底哪个更快啊?

    三、删除节点实验

    直接在控制台输入

    1. innerHTML

    startTime = getTime();
    div.innerHTML = "";
    console.log(getTime() - startTime);
    

    2. DOM操作

    startTime = getTime();
    for (var i = 0; i < elNum * 2; i += 1) {
      div.removeChild(div.firstChild)
    }
    console.log(getTime() - startTime);
    

    3. 实验结果

    innerHTML:

    DOM操作:

    其实差距也是没多大的

    四、添加文本操作

    用innerHTML简单添加文本,与DOM操作添加文本节点对比。

    注意这里添加的只是单个文本节点,不是多个。

    整体代码:

    /* =============== 通过innerHTML添加节点 =============== */
    
    console.log('用innerHTML添加' + elNum + '个Hello World文本:');
    startTime = getTime(); // 开始计时
    for (var i = 0; i < elNum; i += 1) {
      iHtml += "Hello World";
    }
    div.innerHTML = iHtml;
    console.log(getTime() - startTime);
    
    /* =============== 通过DOM操作添加节点 =============== */
    
    console.log('用DOM操作添加' + elNum + '个Hello World文本:');
    iHtml = '';
    startTime = getTime();
    for (var i = 0; i < elNum; i += 1) {
      iHtml += 'Hello World';
    }
    div.appendChild(document.createTextNode(iHtml));
    console.log(getTime() - startTime);
    

    测试结果:

    对于单纯的添加文本,还是DOM操作来的实在

    五、个人看法

    综上,《DOM启蒙》和《高程3》上说的都没有错,是我的错!

    首先,《高程3》上讲的innerHTML在处理添加大量节点的操作上是要比DOM操作要更块,性能更好

    而《DOM启蒙》上说的对于简单的文本操作,还是用DOM操作来完成也确实没错。

    相关文章

      网友评论

          本文标题:innerHTML与DOM操作性能比较

          本文链接:https://www.haomeiwen.com/subject/iuymzttx.html