很多人喜欢用innerHTML来实现动态内容,因为相比dom的操作来说,即简单又实用
但我却很少拿innerHTML来实现动态列表,innerHTML最多只是拿来显示一些名称等文本类的信息废话不多说,自己拿下面的代码做个实验,明白道理的自然OK,不明白的把运行结果贴出来看看就知道
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script language="javascript" type="text/javascript">
function Append() {
var n = parseInt(document.getElementById("tbTimes").value);
var content = document.getElementById("tbContent").value;
var startTime = (new Date()).getTime();
var div = document.getElementById("divContent");
div.innerHTML = "";
for (var i = 0; i < n; i++) {
var item = document.createElement("span");
item.appendChild(document.createTextNode(content));
div.appendChild(item);
}
var endTime = (new Date()).getTime();
document.getElementById("tbTime").value = endTime - startTime;
}
function InnerHtml() {
var n = parseInt(document.getElementById("tbTimes").value);
var content = document.getElementById("tbContent").value;
var startTime = (new Date()).getTime();
var div = document.getElementById("divContent");
div.innerHTML = "";
for (var i = 0; i < n; i++) {
div.innerHTML += "<span>" + content + "</span>";
}
var endTime = (new Date()).getTime();
document.getElementById("tbTime").value = endTime - startTime;
}
function JoinInnerHtml() {
var n = parseInt(document.getElementById("tbTimes").value);
var content = document.getElementById("tbContent").value;
var startTime = (new Date()).getTime();
var div = document.getElementById("divContent");
div.innerHTML = "";
var result = [];
//var result = "";
for (var i = 0; i < n; i++) {
result.push("<span>" + content + "</span>");
//result += "<span>" + content + "</span>";
}
div.innerHTML = result.join("");
//div.innerHTML = result;
var endTime = (new Date()).getTime();
document.getElementById("tbTime").value = endTime - startTime;
}
</script>
</head>
<body>
内容<input id="tbContent" type="text" value=" [Hello World] " /><br />
次数<input id="tbTimes" type="text" value="1000" /><br />
耗时<input id="tbTime" type="text" /><br />
<input type="button" value="appendChild" onclick="Append()"/>
<input type="button" value="innerHTML" onclick="InnerHtml()" />
<input type="button" value="join+innerHTML" onclick="JoinInnerHtml()" />
<div id="divContent">
</div>
</body>
</html>
从结果可以看出,同样次数的dom操作,绝对要比innerHTML要快得多
第三种方法看似最快,但实际上它只有一次innerHTML的赋值
但我却很少拿innerHTML来实现动态列表,innerHTML最多只是拿来显示一些名称等文本类的信息废话不多说,自己拿下面的代码做个实验,明白道理的自然OK,不明白的把运行结果贴出来看看就知道
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script language="javascript" type="text/javascript">
function Append() {
var n = parseInt(document.getElementById("tbTimes").value);
var content = document.getElementById("tbContent").value;
var startTime = (new Date()).getTime();
var div = document.getElementById("divContent");
div.innerHTML = "";
for (var i = 0; i < n; i++) {
var item = document.createElement("span");
item.appendChild(document.createTextNode(content));
div.appendChild(item);
}
var endTime = (new Date()).getTime();
document.getElementById("tbTime").value = endTime - startTime;
}
function InnerHtml() {
var n = parseInt(document.getElementById("tbTimes").value);
var content = document.getElementById("tbContent").value;
var startTime = (new Date()).getTime();
var div = document.getElementById("divContent");
div.innerHTML = "";
for (var i = 0; i < n; i++) {
div.innerHTML += "<span>" + content + "</span>";
}
var endTime = (new Date()).getTime();
document.getElementById("tbTime").value = endTime - startTime;
}
function JoinInnerHtml() {
var n = parseInt(document.getElementById("tbTimes").value);
var content = document.getElementById("tbContent").value;
var startTime = (new Date()).getTime();
var div = document.getElementById("divContent");
div.innerHTML = "";
var result = [];
//var result = "";
for (var i = 0; i < n; i++) {
result.push("<span>" + content + "</span>");
//result += "<span>" + content + "</span>";
}
div.innerHTML = result.join("");
//div.innerHTML = result;
var endTime = (new Date()).getTime();
document.getElementById("tbTime").value = endTime - startTime;
}
</script>
</head>
<body>
内容<input id="tbContent" type="text" value=" [Hello World] " /><br />
次数<input id="tbTimes" type="text" value="1000" /><br />
耗时<input id="tbTime" type="text" /><br />
<input type="button" value="appendChild" onclick="Append()"/>
<input type="button" value="innerHTML" onclick="InnerHtml()" />
<input type="button" value="join+innerHTML" onclick="JoinInnerHtml()" />
<div id="divContent">
</div>
</body>
</html>
从结果可以看出,同样次数的dom操作,绝对要比innerHTML要快得多
第三种方法看似最快,但实际上它只有一次innerHTML的赋值
解决方案 »
- 求救啊!javascript拼接问题
- js改变样式
- javascript版块的兄弟们,你们是美工还是程序员?一直做的应用程序开发,现在想做Web开发呢
- 急,请资深专家进,javascript节点空格问题?
- 求一个JAVASCRIPT验证时间的函数,谢谢了~~
- 滚动文字问题!
- 何解?Date的 Date() toLocaleString() 及 getMonth()
- 请问我这里从网上找来的打印设置代码怎么用
- 为何网页中加了一个Flash影片,速度就非常慢?
- 用JAVASCRIPT如何控制和监控计算机的进程??
- 计算字符串长度
- document.location和document.location.href有什么区别?
方法二慢在字符串的 "+" 操作... 不是innerHTML
额,修改来测试了下,确实是innerHTML消耗
同样消耗大的还有document.getElementById() 方法
appendChild平均在250左右。ie8,ff3
还有,方法二明明就是慢在 + 号上了,js中字符串是不变的对象,都是执行字符串 + 都会重新创建一个字符串。
var startTime = (new Date()).getTime();
var a="";
for (var i = 0; i < 10000; i++) {
a += "<span>" + "</span>";
}
var endTime = (new Date()).getTime();
alert(endTime - startTime);
}function pushString(){
var startTime = (new Date()).getTime();
var result = [];
for (var i = 0; i < 10000; i++) {
result.push("<span>" + "</span>");
}
result.join("");
var endTime = (new Date()).getTime();
alert(endTime - startTime);}结果显而易见
innerHTML插进去的想要接着用多少有些麻烦。
var str = "";
//var str = [];
var startTime = (new Date()).getTime();
for (var i = 0; i < 100000; i++) {
str += "xxxx";
//str.push("xxxx");
}
//var result = str.join("");
var endTime = (new Date()).getTime();
alert( endTime-startTime);
}
首先第二种方法就不说了,只需要1000次的事情做了500500次,谁真这么做谁有毛病;
第一种和第三种方法,理想情况下说应该是差别不大,可能的影响有:
1.前面有人提到了,每次DOM操作都要刷新页面,这是个很浪费的操作。但是这是可以优化的,如果浏览器对此做了优化,就不会造成这么严重的影响。
2.字符串操作好像都被妖魔化了,大家都觉得是洪水猛兽,那有多少人真的去测过字符串操作呢?相信多数人都是从其他语言的字符串操作推测出来的吧?不可以说完全没有影响,不过其实没有想象的那么猛。
个人猜测可能是因为第一个原因,Chrome下LZ的程序测试结果是第一种最快,而其他浏览器下都是第三种最快。但是就算在Chrome下,如果刷新页面后第一次操作就试第三种,其结果跟第一种方式几乎是一样快的,这个就解释不了了。
结论:谁快谁慢还是跟浏览器有关,并且innerHTML往往用起来更方便,因为AJAX返回的始终是字符串,又不是DOM对象。所以我还是偏向于innerHTML
另外,innerHTML的效率是没问题的,只是有点随意,对我来说真正用得多的是插入位置可控的insertAdjacentHTML。
很少用到insertAdjacentHTML,查了一下文档小试了一下,好像浏览器不兼容。Chrome是可以的,Firefox不支持。
Chrome的JS V8引擎效率非常高,虽然在Sun的评测下综合得分稍低于Firefox3.5,但是在Google自己的评测网站下却是Chrome遥遥领先Firefox3.5。就我自己使用到的部分来看,总体感觉是Chrome的JS效率要高于其他浏览器,非常喜欢。
我的项目是一个纯ajax的项目,有大量的js代码,GC下经常出现当前窗口不响应的情况。
另外insertAdjacentHTML原本只有IE支持,不过FF有insertBefore方法,可以代替。
以下是可以跨浏览器的方法
window.insertHTML = function(where, el, html){
if(el.insertAdjacentHTML){
switch(where){
case "BeforeBegin": el.insertAdjacentHTML(where, html); return el.previousSibling; break;
case "AfterBegin": el.insertAdjacentHTML(where, html); return el.firstChild; break;
case "BeforeEnd": el.insertAdjacentHTML(where, html); return el.lastChild; break;
case "AfterEnd": el.insertAdjacentHTML(where, html); return el.nextSibling; break;
}
throw '未知的插入点 -> "' + where + '"';
}else{
var range = el.ownerDocument.createRange(); var frag;
switch(where){
case "BeforeBegin": range.setStartBefore(el); frag = range.createContextualFragment(html); el.parentNode.insertBefore(frag, el); return el.previousSibling; break;
case "AfterBegin": if(el.firstChild){range.setStartBefore(el.firstChild); frag = range.createContextualFragment(html); el.insertBefore(frag, el.firstChild); return el.firstChild;}else{el.innerHTML = html; return el.firstChild;} break;
case "BeforeEnd": if(el.lastChild){range.setStartAfter(el.lastChild); frag = range.createContextualFragment(html); el.appendChild(frag); return el.lastChild;}else{el.innerHTML = html; return el.lastChild;} break;
case "AfterEnd": range.setStartAfter(el); frag = range.createContextualFragment(html); el.parentNode.insertBefore(frag, el.nextSibling); return el.nextSibling; break;
}
throw '未知的插入点 -> "' + where + '"';
}
}