我正在创建一个firefox插件,用html文本中的其他单词添加单词。这段代码有效,但是当迭代一本巨大的字典时,我得到了一个没有响应的脚本错误。
提高此循环速度的最佳方法是什么?
将字典拆分成较小的对象?或设置timeout function?
var brands = {"manykeys" : "manyvalues"};
function replaceWord(){
for (var key in brands){
htmlreplace(key, key + " (" + brands[key] + ")");
}
}
function htmlreplace(a, b, element) {
if (!element) element = document.body;
var nodes = element.childNodes;
for (var n=0; n<nodes.length; n++) {
if (nodes[n].nodeType == Node.TEXT_NODE) {
var r = new RegExp(a, 'g');
nodes[n].textContent = nodes[n].textContent.replace(r, b);
} else {
htmlreplace(a, b, nodes[n]);
}
}
}
replaceWord();
答案 0 :(得分:0)
我没有尝试过,但这样做可能会有效:
function replaceWord(){
for (var key in brands){
(function(key) {
setTimeout(function() {
htmlreplace(key, key + " (" + brands[key] + ")");
}, 0);
})(key);
}
}
我们的想法是,当浏览器有时间推迟替换时,而不是整体地进行替换,并使浏览器在思考时冻结。
答案 1 :(得分:0)
需要考虑一些因素。这取决于你能改变什么。您可以做的更大改进之一是使用数组而不是键/值对象。
var brands = [
['manykeys0000','manyvalues0000'],
['manykeys0001','manyvalues0001'],
['manykeys0002','manyvalues0002'],
['manykeys0003','manyvalues0003'],
['manykeys0004', ...
];
function replaceWord(){
var i, n = brands.length;
for (i = 0; i < n; ++i) {
htmlreplace(brands[i][0], brands[i][0] + " (" + brands[i][1] + ")");
}
}
其他一些变化也应该有一点改进:
1。)将nodes.length
移到循环外面
2.)如果合适的document.body
来自replaceWord()
var body = document.body;
...
htmlreplace(brands[i][0], brands[i][0] + " (" + brands[i][2] + ")", body);
function htmlreplace(a, b, element) {
var nodes = element.childNodes, len = nodes.length;
for (var n=0; n < len; ++n) {
Chrome和Firefox的快速基准测试结果使速度提高了30-40%。
要测试的其他修改:
将var r = new RegExp(a, 'g');
移至replaceWord()
,并将其作为第一个参数传递给htmlreplace()
而不是a
。
function replaceWord(){
var i, n = brands.length;
for (i = 0; i < n; ++i) {
var r = new RegExp(brands[i][0], 'g');
htmlreplace(r, brands[i].join(' (') + ')', elem);
}
}
如果你玩超时this article可能会有兴趣。它使用
window.postMessage();
实施自定义setZeroTimeout()
,但不确定它会如何影响您的情况。
答案 2 :(得分:0)
代码中的瓶颈不是字典大小,除非它真的很大,但DOM遍历。
获取文本节点一次,然后使用它们。
var textnodes = $x("//text()", document.body)
function $x(p, context) {
if (!context) context = document;
var i, arr = [], xpr = document.evaluate(p, context, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for (i = 0; item = xpr.snapshotItem(i); i++) arr.push(item);
return arr;
}
你应该看到相当大的速度提升。