为什么这个jQuery代码比这个慢得多?

时间:2017-11-08 08:25:23

标签: javascript jquery

我有2个Div像列,每列都有内部div,内容不同,如下所示:
image for the HTML layout
(我将“内部div”称为“行”)。

第1列中第1行的文本是第2列中第1行的转换,
第1列中第2行的文本是第2列中第2行的转换,
第1列中第3行的文本是第2列中第3行的转换,
等等。
我需要做的是:
第1列中的第1行应与第2列中的第1行对齐,
第1列中的第2行应与第2列中的第2行对齐,
第1列中的第3行应与第2列中的第3行对齐,
等等。

所以不是这样的: non-aligned lines 我希望它像这样aligned (equal Heights) lines

我用这段代码实现了这个目标

  var t0 = performance.now();
  var leftArray = $('#left .line').map(function(i) {
    return $(this).height();
  });
  var rightArray = $('#right .line').map(function(i) {
    return $(this).height();
  });
  for (var i = 0; i < leftArray.length; i++) {
    if (leftArray[i] < rightArray[i]) {
     $('#left .line').eq(i).css('height', rightArray[i])
    } else if (leftArray[i] > rightArray[i]) {
     $('#right .line').eq(i).css('height', leftArray[i])
   }
 }

对于2列div来说效果很好且速度相当快(300行/列为55ms)。

现在我想更改代码以支持更多列数(想象一下,我有彼此相邻的3或4列,并希望将每行与对应的列对齐。)

所以我更改了代码以从每列获取具有相同索引的行 并使用Math.max计算最大行高并将其应用于具有该索引的所有行,如此

    //number of lines/column
    var column_lines_count =$('.lines').get(0).childElementCount;

    var elementHeights,target,maxHeight;
    for (var i = 1; i < column_lines_count; i++) {

     //get lines with the same index from each column
       target = $('[data-row="'+i+'"]');

    //retun height for each line
       elementHeights = target.map(function() {
          return $(this).height();
       }).get();

      //get the max height
      maxHeight = Math.max.apply(null, elementHeights);

      //set the max heights for all lines with this index number 
      $('[data-row="'+i+'"]').css('height', maxHeight); 
    }   

但是当我在2列上以3oo行/列执行此函数时,它将占用(2000ms)。

所以我更改了代码并改为使用.reduce,这允许我保存具有最大高度的行索引,以便在将max height设置为元素(其他行)时可以忽略它

这是我使用的代码

        //number of lines/column
        var column_lines_count =$('.lines').get(0).childElementCount

        var target,realArray,maxHeight,index_max_height,next_h=0;
        for (var i = 1; i < column_lines_count; i++) {

         //get lines with the same index from each column
         target = $('[data-row="'+i+'"]');

         //Convert to array so we can use reduce
         realArray =  $.makeArray( target );

         //variable to save the index of the line that has the maximum height, so we don't have to set the height for it. 
         index_max_height=0

           /*
           * Reduce=>
           * intial value => $(realArray[0]).height()
           * next is represents the line
           * index = index of that line
            */  
           maxHeight = realArray.reduce(function(biggerHeight, next,index) {
             next_h = $(next).height();
             if(biggerHeight > next_h){
               return biggerHeight;
             } else{
               index_max_height =index;
               return next_h; 
             }
           }, $(realArray[0]).height());        

       /*
        *for elements (lines) that has index != index of max_height line - set the max height
        *
        */
        $.map( target, function( a, index ) {
            if(index != index_max_height){
              $(a).css('height', maxHeight);    
          }
        });

     }  

使用此代码(在具有3oo行/列的2列上)约。 (1400ms)。

这里有3个案例的小提琴:
https://jsfiddle.net/gc4xL36g/

为什么最后两个函数比第一个慢得多? 如果我有超过2列,我如何改进代码?

更新:
////////////////////////////////////////////////// ///////////////
正如@Icepickle在评论中提到的那样

  

选择很昂贵

所以我更改了代码并在循环外只使用了一个选择器并将其保存在循环内部使用的变量中。它节省了几毫秒,但它仍然远离第一个代码,我认为大部分需要时间是计算我使用reduce实现的相应行之间的最大高度,我很感激,如果有建议要做这个更快

这是新代码:

  var number_of_columns = $('.lines').length;     
  var lines = $('.line');
  var column_lines_count =lines.length/2;
  var realArray,maxHeight,index_max_height,next_h=0;

  for (var i = 1; i < column_lines_count; i++) {
    var corresponding_lines = [];
    var mindex;
    for(var j=0; j < number_of_columns; j++){
      mindex = i-1+(j*column_lines_count);
      corresponding_lines.push(lines[mindex]);
     }

     //Convert to array so we can use reduce
     realArray =  $.makeArray( corresponding_lines );

     //variable to save the index of the line that has the maximum height, so we don't have to set the height for it. 
      index_max_height=0


    /*
     * Reduce=>
     * intial value => $(realArray[0]).height()
     * next is represents the line
     * index = index of that line
     */

    maxHeight = realArray.reduce(function(biggerHeight, next,index) {
    next_h = $(next).height();
    if(biggerHeight > next_h){
        return biggerHeight;
    } else{
       index_max_height =index;
       return next_h; 
    }
    }, $(realArray[0]).height());       

    /*
     *for elements (lines) that has index != index of max_height line - set the max height
     *
     */
     $.map( corresponding_lines, function( a, index ) {
      if(index != index_max_height){
        $(a).css('height', maxHeight);  
      }
     });

    }   

1 个答案:

答案 0 :(得分:0)

正如@DanielBeck所建议的

  

预先计算数组中的高度,而不是每次都从DOM中读取它们

解决问题,
这是新代码,它比第一个代码

更快
 var number_of_columns = $('.lines').length;

 var lines = $('.line');
 var column_lines_count =lines.length/number_of_columns;
 var leftArray = lines.map(function(i) {
     return $(this).height();
 }); 
 var realArray,maxHeight;

 for (var i = 1; i < column_lines_count; i++) {
      var corresponding_lines = [];
      var mindex;
      for(var j=0; j < number_of_columns; j++){
          mindex = i-1+(j*column_lines_count);
           corresponding_lines.push(leftArray[mindex]);
     }

    //Convert to array so we can use reduce
     realArray =  $.makeArray( corresponding_lines );


   maxHeight = realArray.reduce(function(biggerHeight, next,index) {   
      if(biggerHeight > next){
        return biggerHeight;
      } else{
        return next; 
      }
    }, realArray[0]);       

    $('[data-row="'+i+'"]').css('height', maxHeight);   
  }