【问题标题】:My $.each loop is quite slow. Any methods of making it faster?我的 $.each 循环很慢。有什么方法可以加快速度吗?
【发布时间】:2015-08-30 05:34:06
【问题描述】:

我有一个 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 行吗?

谢谢:)

【问题讨论】:

  • 如果你需要一种搜索​​方法,你可以使用一些研究算法,比如二分法搜索。

标签: javascript jquery performance


【解决方案1】:

试试这个:

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() 的回调接收到正在迭代的元素,您无需再次选择它。

此解决方案可能无法完全解决您的问题,但至少是我在不了解更多细节的情况下能想到的最有效的方法。

【讨论】:

    【解决方案2】:

    这里有几个想法:

    • $("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);
            }
        }
    });
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 我正在尝试将我的 each 数组转换为 for 循环,但它似乎对我不起作用.. 你能否根据我的 @987654326 引导我进入正确的方向@循环在帖子中?
      • jQuery 的 each 方法在该块上引起的开销是一个小问题,与之前的迭代相比,在每个循环上进行 $() 选择......在我的回答中,我提出了一个不同的策略避免此类操作。
      【解决方案4】:

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

      所以至少我会建议替换这个:

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

      通过这个:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-21
        • 2019-06-28
        • 2011-01-17
        • 1970-01-01
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        相关资源
        最近更新 更多