Javascript在大字典中循环生成无响应的脚本
Javascript looping through large dictionary yields unresponsive script
我正在制作一个firefox插件,在html文本中添加单词和其他单词。这段代码可以工作,但是当遍历一个巨大的字典时,我得到一个无响应的脚本错误。
提高循环速度的最佳方法是什么?
将字典拆分为更小的对象?或者设置一个超时函数?
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();
有一些需要考虑的问题。这在很大程度上取决于你能改变什么。你可以做的一个更大的改进是使用数组而不是键/值对象。
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)。如适宜,由replaceWord()
传document.body
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);
}
}
如果你玩超时,这篇文章可能会感兴趣。它使用
window.postMessage();
实现自定义setZeroTimeout()
,但不确定它将如何影响您的情况。
除了JSPerf等,在浏览器中使用分析工具,例如在Chrome中,这可能更适合你在代码中做的事情。
我还没有试过,但这样做可能会起作用:
function replaceWord(){
for (var key in brands){
(function(key) {
setTimeout(function() {
htmlreplace(key, key + " (" + brands[key] + ")");
}, 0);
})(key);
}
}
这个想法是你推迟替换当浏览器有时间,而不是做它的单一和使浏览器冻结,而它正在思考。
代码中的瓶颈不是字典的大小,除非它真的很大,而是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;
}
您应该会看到相当大的速度提高。
相关文章:
- 真的没有办法在Firefox中自动杀死没有响应的脚本吗
- 如何获取从 AJAX 到脚本的发送响应
- 为什么我的附加组件面板的内容脚本在更改 contentURL 后不再响应端口消息
- 如果HTTP响应为404,脚本标记会被阻塞吗
- 将简单的Perl脚本翻译成Python,向客户端发送响应
- 如何在java脚本中从http响应生成blob
- 在Java(Coffee)脚本中获取响应值
- 当我使用java脚本调用web服务时,模拟器上没有得到响应
- 加速谷歌脚本中的onEdit功能-有时没有响应
- Java脚本将URL的响应读取到变量中
- 避免'脚本没有响应'使用反向AJAX/Comet
- F5负载平衡器附加<脚本>到JSON Ajax响应
- Javascript随机名称猜测者:无响应的脚本问题
- 避免“;无响应脚本"foreach循环中的消息
- 网站响应脚本
- 如何编辑此表响应脚本
- 避免无响应脚本的跨浏览器方式
- IE8 中的 setTimeOut 和无响应脚本出现问题
- 无响应脚本错误
- RadImageEditor onSaving Event不允许发送响应脚本