【问题标题】:Improving Efficiency in jQuery function提高jQuery函数的效率
【发布时间】:2009-05-22 00:59:17
【问题描述】:

此函数中的while语句在IE/firefox中运行太慢(阻止页面加载4-5秒),但在safari中运行速度很快...

它正在测量页面上文本的像素宽度并截断直到文本达到理想宽度:

function constrain(text, ideal_width){

    $('.temp_item').html(text);
    var item_width = $('span.temp_item').width();
    var ideal = parseInt(ideal_width);
    var smaller_text = text;
    var original = text.length;

    while (item_width > ideal) {
        smaller_text = smaller_text.substr(0, (smaller_text.length-1));
        $('.temp_item').html(smaller_text);
        item_width = $('span.temp_item').width();
    }

    var final_length = smaller_text.length;
    if (final_length != original) {
        return (smaller_text + '…');
    } else {
       return text;
    }
}

有什么方法可以提高性能?如何将其转换为冒泡排序函数?

谢谢!

【问题讨论】:

  • 这不是真正的排序问题,冒泡排序也是你能做的最慢的排序。

标签: javascript jquery


【解决方案1】:

将调用 $() 移到循环之外,并将其结果存储在一个临时变量中。除了调用 .html() 之外,运行该函数将是代码中最慢的事情。

他们非常努力地使库中的选择器引擎快速运行,但与普通的 javascript 操作(例如在本地范围内查找变量)相比,它仍然很慢,因为它必须与 dom 交互。特别是如果您使用这样的类选择器,jquery 必须遍历文档中的每个元素,查看每个类属性并在其上运行正则表达式。每次循环!尽可能多地从你的紧密循环中取出这些东西。 Webkit 运行速度很快,因为它有 .getElementsByClassName 而其他浏览器没有。 (还)。

【讨论】:

  • 这确实看起来很合理,我自己没有尝试过。想知道调用 html() 以在 DOM 中插入较短的字符串是否也有牵连(即,它们是否会触发渲染)?
  • 是的,应该可以。它将使您的代码更快,但也许更重要的是,更易于维护,符合 DRY 原则。例如,如果您意识到 temp_item 实际上应该是一个 id 而不是一个类,您将不得不在四个地方更改代码。错过一个,你可能会拉你的头发一段时间。如果您遵循 Breton 的建议,您只需进行一项更改。
【解决方案2】:

您可以使用binary search,而不是每次删除一个字符直到找到理想的宽度。

【讨论】:

    【解决方案3】:

    我看到问题在于您通过设置 temp_item 的 html 来不断修改循环中的 DOM,然后重新读取宽度。

    我不知道您的问题的背景,但从我的角度来看,尝试通过测量渲染元素来调整布局并不是一个好习惯。

    也许您可以从不同的角度解决问题。截断到固定宽度很常见。

    如果没有选择,其他可能性(hack?)可能是使用容器元素的溢出 css 属性并将 ... 放在文本旁边的其他元素中。虽然我建议您重新考虑按照您的意图解决问题的必要性。

    雨果

    【讨论】:

      【解决方案4】:

      除了 Breton 的建议之外,加快算法速度的另一种可能性是对文本长度使用二进制搜索。目前,您一次将长度减少一个字符 - 这是字符串长度的 O(N)。相反,使用 O(log(N)) 的搜索。

      大致上是这样的:

      function constrain(text, ideal_width){
      

      ...

          var temp_item = $('.temp_item');
          var span_temp_item = $('span.temp_item');
      
          var text_len_lower = 0;
          var text_len_higher = smaller_text.length;
      
          while (true) {
                if (item_width > ideal)
                {
                  // make smaller to the mean of "lower" and this
                  text_len_higher = smaller_text.length;
                  smaller_text = text.substr(0, 
                      ((smaller_text.length + text_len_lower)/2));
                }
                else
                {
                  if (smaller_text.length>=text_len_higher) break;
      
                  // make larger to the mean of "higher" and this
                  text_len_lower = smaller_text.length;
                  smaller_text = text.substr(0, 
                      ((smaller_text.length + text_len_higher)/2));
                }
                temp_item.html(smaller_text);
                item_width = span_temp_item.width();
          }
      

      ... }

      【讨论】:

        【解决方案5】:

        需要注意的一点是,每次向 DOM 添加内容,或更改节点中的 html 时,页面都必须重新绘制自身,这是一项昂贵的操作。将任何 HTML 更新移出循环可能有助于加快速度。

        正如其他人所提到的,您可以将对 $() 的调用移到循环之外。您可以创建对元素的引用,然后在循环中调用其上的方法,如 1800 INFORMATION 所述。

        如果您将 Firefox 与 Firebug 插件一起使用,则有一种很好的方法来分析代码以查看花费时间最长的部分。只需单击第一个选项卡下的配置文件,执行您的操作,然后再次单击配置文件。它将显示一个表格,其中包含代码的每个部分所花费的时间。您可能会在列表中看到很多在您的 js 框架库中的东西;但是您也可以通过一些试验和错误来隔离它。

        【讨论】:

          猜你喜欢
          • 2020-09-19
          • 2023-03-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多