我有这个函数运行返回的json数据。它的速度非常快,但IE和FF速度很慢。关于如何改进这个的建议?返回的数据大约是15个对象。这会在顶部创建一堆锚点,每个标题下都有列表。
function list_response(jsonData) {
"use strict";
var lists = document.getElementById("lists"), anchors = document.getElementById("anchors"), jItems = jsonData.items;
jItems.sort(function (a, b) {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
});
for (var i = 0; i < jItems.length; i++) {
var pList = jItems[i], str = "", ank = "";
str += '<span class="backtotop">[ <a href="#">Back to top</a> ]</span><br /><br /><br /><li class="title nodot"><a class="pHeader" name="' + pList.name + '"><h2>' + pList.name + '</h2></a></li>';
ank += '<a class="pHeader" href="#' + pList.name + '">' + pList.name + '</a> ';
lists.innerHTML += str;
anchors.innerHTML += ank;
for (var j = 0; j < jsonData.items[i]["videos"].length; j++) {
var vList = jsonData.items[i]["videos"][j];
var strs = "";
strs += '<li class="nodot"><a href="https://www.site.org/videos/Video_Player.page?bctid=' + vList.id + '">' + vList.name + '</a></li>';
lists.innerHTML += strs;
}
}
}
答案 0 :(得分:4)
以下是代码的一个版本,它结合了以下性能增强功能:
jItems.length
为20
且平均视频数为5,则会将DOM事务数量减少到DOM事务数量的1/50。.push()
将字符串数据累积到数组中,并在最后执行.join()
,而不是每次都添加到字符串的末尾。 JS引擎通常可以比连接每个片段更有效地连接大量字符串。pList
,然后有四个对pList.name
的引用,只需获取一次名称值并直接使用它。jItems[i]
因为它引用了几个地方而不是每次重新计算它。for
循环的len变量并与之进行比较,而不是在每次迭代时重新计算它。jItems[i]["videos"]
一次,而不是每次在内循环中重做它。jsonData.items
中有大量项目,则排序算法效率不高,因为每次比较都必须重新计算每个名称的小写版本。您可以在一次传递中预编译所有小写版本(每个项目一次),然后在排序算法中使用它们,而不是每次比较两个项目时都必须重做它们。这些更改导致此代码:
function list_response(jsonData) {
"use strict";
var lists = document.getElementById("lists"), anchors = document.getElementById("anchors"), jItems = jsonData.items;
var results = [], anks = [], vList, pListName, item, videoItem;
// precache all lower case versions to make sorting faster
var i, iLen = jItems.length, j, jLen;
for (var i = 0; i < iLen; i++) {
jItems[i].nameLower = jItems[i].name.toLowerCase();
}
jItems.sort(function (a, b) {
return a.nameLower.localeCompare(b.nameLower);
});
for (i = 0; i < iLen; i++) {
item = jItems[i]; // cache for use in loops
videoItem = item["videos"]; // cache for use in loops
pListName = item.name; // cache for use in multiple places
results.push('<span class="backtotop">[ <a href="#">Back to top</a> ]</span><br /><br /><br /><li class="title nodot"><a class="pHeader" name="' + pListName + '"><h2>' + pListName + '</h2></a></li>');
anks.push('<a class="pHeader" href="#' + pListName + '">' + pListName + '</a> ');
for (j = 0, jLen = videoItem.length; j < jLen; j++) {
vList = videoItem[j];
results.push('<li class="nodot"><a href="https://www.site.org/videos/Video_Player.page?bctid=' + vList.id + '">' + vList.name + '</a></li>');
}
}
lists.innerHTML += results.join("");
anchors.innerHTML += anks.join("");
}
答案 1 :(得分:2)
您可以尝试长度缓存 - 例如,创建变量l = jItems.length
,并在for
循环的条件下使用它,而不是每次都获取length
属性 - 具体取决于实现查找数组的长度通常会有一些开销,所以如果你有一个大数组,这个差异就会很明显。
此外,创建临时变量以保持str
和ank
字符串变大,然后只将它们放在最后的innerHTML
右边。
答案 2 :(得分:1)
你不应该使用字符串和innerHTML来构建HTML。你应该使用DOM。
答案 3 :(得分:1)
老技巧,不太确定它是否相关,但
var builder = [];
builder.push('foo');
builder.push('bar');
builder.push('baz');
var str = builder.join('')
在IE中比
快得多var str = '';
str += 'foo';
str += 'bar';
str += 'baz';
答案 4 :(得分:0)
var strHTML = "";
var ankHTML = "";
for (var i=0; i < jItems.length; i++){
...
strHTML += str;
ankHTML += ank;
...
}
lists.innerHTML = strHTML ;
anchors.innerHTML = ankHTML ;
答案 5 :(得分:0)
这里的主要性能瓶颈无疑是您使用innerHTML的方式。
el.innerHTML += aString;
当然等同于el.innerHTML = el.innerHTML + aString;
。
这意味着对于每次调用,DOM将被序列化为HTML字符串,然后反序列化为有效的DOM。这是很多不必要的工作。
相反,要么:
(a)预先构建所有HTML并为每个元素分配innerHTML一次。
(b)将元素或文档片段附加到父节点。