我的$ .each循环很慢。任何使它更快的方法?

时间:2015-06-14 18:30:44

标签: javascript jquery performance

我有一个Chrome扩展程序,需要查看网页上的每个<p></p>。我的chrome扩展程序会查看p文本并检查文本是否位于数组中。问题是,阵列有超过3,000个元素,如果可能的话,我很想达到12,000或更多。

按照目前的速度,这是不可行的,因为它使网页加载页面大约需要4秒钟。我的chrome扩展程序在文档末尾运行,因此用户可以在技术上浏览网站,只需4秒即可加载所有内容。

这是我的代码:

$.each(arrayObj, function(key, value) {
      $("p").highlight(key, {caseSensitive: true, className: 'highlight-882312', wordsOnly:true });
});

$('.highlight-882312').each(function() {    

    var currentKey = $(this).text();
    console.log(currentKey);

//do something else here that doesn't really 
//apply to the question as it only runs when the user hovers over the class.

});

然后数组看起来很简单:

var arrayObj = {

"keyword1": 'keyword_1_site',
"keyword2": 'keyword_2_site',
... etc
... 3,000+ more lines ...
...

}

我认为$.each不是最有效的,正如我所说,4秒加载是相当多的。我能做些什么来提高效率吗?我是否能够在阵列中击中12,000行?

谢谢:)

4 个答案:

答案 0 :(得分:0)

试试这个:

var p = $("p");
$.each(arrayObj, function(key, value) {
  p.highlight(key, {caseSensitive: true, className: 'highlight-882312', wordsOnly:true });
});

$('.highlight-882312').each(function(idx, element) {    
  var currentKey = element.text();
  console.log(currentKey);

  // other stuff
});

一般来说,您希望避免在循环内部使用$()选择器,因为它们非常耗时。请注意each()的回调接收正在迭代的元素,您不需要再次选择它。

这个解决方案可能无法完全解决您的问题,但至少是最有效的方法,我可以在不了解更多细节的情况下进行思考。

答案 1 :(得分:0)

以下是一些想法:

  • $("p").highlight()选项是静态的,因此请定义一次,使用多个。
  • 仅将.highlight()应用于页面上实际存在的字词。
var options = {
        caseSensitive: true,
        className: 'highlight-882312',
        wordsOnly:true
    },
    arrayObj_ = {},
    $p = $("p");

//Populate arrayObj_ with true for every word that exists on the page
$p.each(function() {
    $(this).text().split(' ').forEach(function(word) {
        arrayObj_[word] = true;
    });
});

//Now loop through arrayObj_ ,
// which is hopefully much smaller than arrayObj,
// and highlight those words that are represted as keys in arrayObj.
$.each(arrayObj_, function(key, value) {
    if(arrayObj[key]) {
        $p.highlight(key, options);
    }
});

不知道这会更快还是更慢。您需要运行测试。

编辑...

更好的是,一次性发现单词并突出显示。

var options = {
        caseSensitive: true,
        className: 'highlight-882312',
        wordsOnly:true
    },
    wordsFound = {},
    $p = $("p");

$p.text().split(/\b/).forEach(function(word) {
    if(!wordsFound[word]) {
        wordsFound[word] = true;
        if(arrayObj[word]) {
            $p.highlight(word, options);
        }
    }
});

答案 2 :(得分:0)

将它们重构为javascript for循环而不是jQuery的each循环。 https://stackoverflow.com/a/14808512/1547497

即。

var elems = $('.highlight-882312');
for (var i = 0; i < elems.length; ++i){

}

答案 3 :(得分:0)

您正在为数组中的每个元素运行全局选择器。那是非常多的。

所以至少我建议更换一下:

$.each(arrayObj, function(key, value) {
      $("p").highlight(key, ...);
});

由此:

var $all_p = $("p");

$.each(arrayObj, function(key, value) {
    $all_p.highlight(key, ...);
});