如何用更高性能的等价替换.each()和.find()等JQuery函数?

时间:2011-09-12 13:49:22

标签: jquery css performance

我如何才能提高以下JQuery代码的性能:

var firstRowCellsWidth = new Array();

function initialize();

    $('table.rgMasterTable > tbody > tr:first > td').each(function () {

            firstRowCellsWidth.push({
                normalCellWidth: $(this).width(),
                firstTemplateCellWidth: $(this).find('table > tbody > tr > td:first').width()
            });
        });
}

我正在使用:first$(this).find(, >each()。这些显然会降低性能?

他们应该替换什么?或者它们的等效原生javascript代码是什么?

我猜测使用for循环而不是each()方法。剩下的呢?

代码的目的: 计算表格每列的宽度。主表还有一个嵌套表,可以看出。

谢谢,

4 个答案:

答案 0 :(得分:2)

var firstRowCellsWidth = [];
function initialize(){
  var tables = document.getElementsByTagName("table");
  for(var i=0; i<tables.length; i++){
    if(/(^|\s)rgMasterTable(\s|$)/.test(tables[i].className)){
      //a className is only valid if the className is contained within a space/nothing(^) and a space/nothing($)

      var tcell = tables[i].rows[0].cells; //Any cell
      for(var j=0; j<tcell.length; j++){
        firstRowCellsWidth.push({
          normalCellWidth:tcell[j].offsetWidth,
          firstTemplateCellWidth:tcell[j].getElementsByTagName("td")[0].offsetWidth
         //the first cell of any row of any table = the first occurence of a TD element
        });
      }
      //break;
      //Uncomment the previous line if you want to enumerate through all tables whose class equals .rgMasterTable
    }
  }
}

尽可能高效,不使用JQuery(懒惰的脚本编写者经常使用框架,他们不介意计算效率的损失)。

请注意,当文档结构与您的描述(tcell[j].getElementsByTagName("td"[0] is undefined)不符时,将引发错误。

编辑:JavaScript与JQUery的速度方面

作为对maxedison(第三条评论)的回应,他质疑我的陈述,即JQuery的效率低于JavaScript。复制下面的代码段并将其粘贴到位置栏(本页)中。将出现一个提示,其中可以指定测试数量。测试运行后,会弹出一个警告,显示执行这些测试所需的毫秒数。提供了两个测试用例:

原生 JavaScript 测试用例:

javascript:alert((function(m){
for(var i=0, t=new Date; i<m; i++){
  document.getElementsByTagName("table")[0].rows[0].cells[0];
}
return (new Date).getTime()-t.getTime();
})(prompt("Native\x20JS,\x20repeat\x20n\x20times:","10000")));

JQuery 测试用例。警告:不要从大量测试开始:

javascript:alert((function(m){
for(var i=0, t=new Date; i<m; i++){
  $("table > tbody > tr > td:first");
}
return (new Date).getTime()-t.getTime();
})(prompt("JQuery,\20repeat\x20n\x20times","10")));

在我1岁的笔记本电脑上,使用FireFox 3.6.22,使用原生JavaScript的 10000 调用等于 5 JQuery执行。

答案 1 :(得分:1)

您实际遇到性能问题吗?看起来这种循环运行的次数并不多,每次迭代节省几毫秒会产生明显的差异。

无论如何,我意识到你可能是出于好奇而问,所以这是一种可以改善表现的方法:

  • 在推送值之前,将$(this)存储在变量中。请记住,$实际上是一个函数,因此$(this)表示您正在调用函数$并将参数传递给它。作为一般经验法则,如果您需要多次使用$(this),将其存储在变量中会更快,因为它可以避免进行额外的$函数调用。

我也很想知道标准for循环是否会明显快于.each()。但是,当你问“它们的等效原生javascript代码是什么?”时,请注意你使用jQuery的全部原因是因为它更容易编写和使用jQuery。阅读,并且大多数“本机javascript”等价物将看起来&amp;要复杂得多。所以这个问题本身就会破坏使用jQuery的目的,除非你真的遇到了一些性能问题。

答案 2 :(得分:0)

一个改进是存储对您打算多次使用的任何jQuery对象的引用。

因此,不要多次使用$(this)使用

var $this = $(this);

从现在开始使用$this来引用该对象..

function initialize(){
    $('table.rgMasterTable > tbody > tr:first > td').each(function () {
            var $this = $(this);
            firstRowCellsWidth.push({
                normalCellWidth: $this.width(),
                firstTemplateCellWidth: $this.find('table > tbody > tr > td:first').width()
            });
        });
}

答案 3 :(得分:0)

用原生循环替换.each可能不会做任何事情,.each只是做一个for循环。

你真的遇到了速度问题吗?

假设您将为表格提供静态布局,您可以找出如何使用.childNodes[]向下导航。你会做类似

的事情
document.getElementById('myTable').childNodes[0].childNodes[0].childNodes[0]

。你可以想象,这很快就变得非常难看。

你可以通过删除> trbody >部分来加快选择器的速度,除非你的trbody中有一个表而trhead中的另一个表没有做任何事情