【问题标题】:Loop of a list of items with javascript使用 javascript 循环项目列表
【发布时间】:2015-10-26 14:20:05
【问题描述】:

我读到,为了提高 jquery 的性能应该避免使用,因为有些事情会变慢一点。 其中包括 each() 方法,并且使用 for 循环是合适的......(根据我阅读的网络文章,方法 each() 大约是 for 循环 javascript 的 10 倍)..

我正在尝试使用js但是我有一些问题:/

jQuery

$('#block-system-main-menu li').each(function () {      
        var text= ($(this).children('a').text());
        if (text == 'Map' || text== 'Vul' || text== 'Equa'){
            $(this).children('a').append('<span style="float:right; margin-right: 15%; line-height: inherit;" class="fa fa-chevron-right"></span>');
        }                   
    }); 

Javascript

var voce= $('#block-system-main-menu li');
for(var i=0; i< voce.length; i++) {
        var text= (voce[i].children('a').text());           
        if (text == 'Map' || text== 'Vul' || text== 'Equa'){
            voce[i].children('a').append('<span style="float:right; margin-right: 15%; line-height: inherit;" class="fa fa-chevron-right"></span>');
        } 
    }

但循环不起作用,我不明白为什么....

谢谢!

【问题讨论】:

  • 在阅读这样的内容时,请记住,速度是非常快的内容的 10 倍,但仍然比其他可能会减慢页面速度的内容快得多。如果循环中的 append 比仅执行 .each 慢得多,我不会感到惊讶。
  • but the loop does not work 它有什么作用?它是如何“不工作”的?它会给你错误吗?它什么都不做吗?它做的事情是否超出了您的预期?
  • 过去有人问过这个问题。查看stackoverflow.com/questions/11887450/…
  • 在for循环示例中voce[i].children('a')应该抛出一个错误,因为节点没有cildren()方法:jsfiddle.net/pap5nxp7Uncaught TypeError: voce[0].children is not a function
  • 第一种方法是 Jquery,第二种方法是 Javascript。 jQuery 是一个 Javascript 库。你不能只是假设,因为 jquery 实现了 javascript 也会做同样的事情。

标签: javascript jquery performance


【解决方案1】:

你的问题就在这里。比较:

var text= ($(this).children('a').text());

与:

var text= (voce[i].children('a').text());

在第一种情况下,您正在使用$(this) 创建一个 jquery 对象。在第二种情况下,你不是。 voce[i] 为您提供了一个 HTML 元素,它没有名为 children 的函数。所以你应该在那里得到一个错误。要使其工作,您需要从voce[i] 创建一个jquery 对象。比如:

var text = $(voce[i]).children('a').text();

或者正如@GuerasArnaud 在他的回答中建议的那样:

var text= voce.eq(i).children('a').text(); 

但是,foreach 很可能并不是降低代码速度的原因。您实际上应该分析您的代码并确定代码中的瓶颈。

虽然当您阅读“x 比 y 慢”时,您当然应该牢记这一点,但您也应该尝试了解它的适用性和实际重要性。我不会在所有情况下都完全避免each,因为有时代码的便利性和可读性比在代码的非关键部分中对代码性能进行微优化更为重要。

另请注意,在您的linked tutorial 中,您已经锁定了foreach 的点,而错过了Cache. ALWAYS. 的点所以在您的jquery 代码中,您将创建$(this) 对象两次(尽管在这种情况下它并不那么重要,因为您没有使用选择器,并且这取决于您的 if 子句评估为 true 的频率,但它仍然是一个不会给您带来任何回报的成本)。

如果你有这个,你的循环会更好:

$('#block-system-main-menu li').each(function () {  
    var children = $(this).children('a');
    var text = children.text();
    if (text == 'Map' || text== 'Vul' || text== 'Equa'){
        children.append('<span style="float:right; margin-right: 15%; line-height: inherit;" class="fa fa-chevron-right"></span>');
    }                   
}); 

或者对于for 循环:

var voce= $('#block-system-main-menu li');
for(var i=0; i< voce.length; i++) {
    var children = $(voce[i]).children('a');
    var text = children.text();           
    if (text == 'Map' || text== 'Vul' || text== 'Equa'){
        children.append('<span style="float:right; margin-right: 15%; line-height: inherit;" class="fa fa-chevron-right"></span>');
    } 
}

但同样,除非voce.length 非常大我怀疑你会发现现实世界的性能有任何显着差异

【讨论】:

    【解决方案2】:

    voce 是一个 jQuery 对象,但 voce[i] 是一个 HTMLNode 元素,它没有 .children() 方法。如果你想留在'jquery like'中,你应该使用.eq()

    var text= voce.eq(i).children('a').text();          
    

    【讨论】:

      【解决方案3】:

      所以我使用 jQuery 方法对 jQuery each 与固定的 JS for 循环进行了基准测试,并添加了一个普通的 JS 解决方案:http://jsperf.com/jquery-each-for-loop

      在我的机器上 jQuery.each 与 JS for 非常接近,而 vanilla JS 的表现要好得多。

      没有jQuery的代码:

      var voce = [].slice.call( document.querySelectorAll('#block-system-main-menu li'));
      /* prepare the span to use .appendChild instead of innerHTML += */
      var span = document.createElement('span');
          span.style.cssText = 'float:right; margin-right: 15%; line-height: inherit';
          span.className = 'fa fa-chevron-right';
      
      for(var i=0;i<voce.length;i++){
         /* get the textContent with innerText fallback */
         var text = voce[i].textContent || voce[i].innerText;
         if (text == 'Map' || text == 'Vul' || text == 'Equa') {
             /* forEach to keep compatibility with .children('a') method which returns a collection. 
                Could be optimized further if you know you need to modify a single element */
             [].forEach.call( voce[i].querySelectorAll('a'), function(a){
                 a.appendChild( span.cloneNode() );
             })
         }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-16
        • 2017-09-13
        • 1970-01-01
        • 1970-01-01
        • 2011-01-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多