innerHTML与DOM操作性能比较

一、故事背景

这周一看《高程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 += "

Hello World

"; // 别这么写: // div.innerHTML += "

Hello World

"; // 因为这样每次循环都有两个操作: // 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. 输出结果

你会发现:

innerHTML与DOM操作性能比较_第1张图片

唉????

但你再刷新试试

innerHTML与DOM操作性能比较_第2张图片

唉????

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

三、删除节点实验

直接在控制台输入

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操作性能比较_第3张图片

其实差距也是没多大的

四、添加文本操作

用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);

测试结果:

innerHTML与DOM操作性能比较_第4张图片

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

五、个人看法

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

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

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

你可能感兴趣的:(innerHTML与DOM操作性能比较)