【问题标题】:Are classes indexed in modern browsers?现代浏览器中的类是否被索引?
【发布时间】:2016-02-26 22:31:15
【问题描述】:

在过去的 Web 开发中,我总是尝试在 javascript 中构造选择器时从 id 继承,之前是在 jQuery 中,最近使用 document.querySelector()/.querySelectorAll()。这是出于性能原因。我在这样的帖子中遵循了建议 (http://www.artzstudio.com/2009/04/jquery-performance-rules/#descend-from-id)。

例如:

$('#new-address-form input.address')

可能比

快很多
$('.address')

即使页面上只有一个元素具有一类地址。如果 DOM 中有很多不同的类,在某些浏览器中这可能会快很多(我在看你的 IE

但是,从经验上看,今天似乎不再是这种情况了。任何人都可以向我指出一些文档或代码,对于开源浏览器,可以确认现代浏览器按类索引元素?

【问题讨论】:

  • $("#id").find(".class");应该更快
  • 好吧,在IE8及以下版本中,没有document.getElementsByClassName,所以在IE9之前,过滤更多会更快。在 IE7 中也没有 querySelectorAll,所以情况更糟。显然,随着浏览器的更新和改进,它们的方法变得更加高效,每个 jQuery 版本都是如此。在这一点上,在遇到性能问题之前几乎没有理由考虑性能,而是采取更具可读性/可维护性的路线。

标签: javascript jquery google-chrome internet-explorer firefox


【解决方案1】:

性能差异是存在的,但除非您使用非常大的标记,否则它可能并不显着。

我设置了一个基准 JS Fiddle,它创建了 20,000 个 div 标签,每个标签嵌套 10 层深。然后尝试根据类随机选择一个,并再次根据 ID 与后代类。

我在这里对其进行了基准测试:https://jsfiddle.net/0wyLfnz8/14/

结果
按 ID 选择然后后代类在 Chrome 中平均为 0.018 毫秒
在 IE 中按 ID 选择后代类平均为 39.33 毫秒

在 Chrome 中仅按类选择平均需要 12.178 毫秒
在 IE 中仅按类选择平均为 51.386 毫秒

同样,这些结果以毫秒为单位,对 20,000 个 HTML 元素进行了 500 次测试

基准测试代码

$(document).ready(function() {
  var d = new Date();
  var st = d.getTime();
  var start = st;
  var et;
  var max = 20000;
  var numberOfTests = 500;
  var elementDepth = 10;
  for(var i = 1; i < max; i++) {
    //lets make a random class too
    r = Math.floor((Math.random() * 10) + 1);
    var depth = "";
    for(var j = 1; j<elementDepth;j++) {
      depth += '<div class="depth' + j + '"></div>'
    }
    $('body').append('<div id="d'+i+'">'+depth+'<div class="depth'+elementDepth+'"><div class="c'+i+' r'+r+'">Hello, I am div number '+i+'</div></div></div>');
  }
  d = new Date();
  var duration = d.getTime() - st;
  console.log('Generating divs took ' + (duration/1000) + ' seconds');

  idDuration = 0;
  idTests = 0;
  for(var i = 0; i < numberOfTests; i++) {
    //choose a random div to select
    r = Math.floor((Math.random() * max) + 1);
    d = new Date();
    st = d.getTime();
    var tagbyID = $('#d'+r+ '.c'+r);
    d = new Date();
    et = d.getTime();
    duration =  et - st;


    //console.log('Selecting by ID took ' + duration + ' milliseconds');
    idDuration += duration;
    idTests++;
  }
  console.log('---');

  classDuration = 0;
  classTests = 0;
  for(var i = 0; i < numberOfTests; i++) {
    //choose a random div to select
    r = Math.floor((Math.random() * max) + 1);
    d = new Date();
    st = d.getTime();
    var tagbyClass = $('.c'+r);
    d = new Date();
    et = et;
    duration = d.getTime() - st;
    //console.log('Selecting by class took ' + duration + ' milliseconds');
    classDuration += duration;
    classTests++;
  }
  console.log('---');
  d = new Date();
  console.log('total duration: ' + ((d.getTime() - start)/1000) + " seconds");
  console.log('---');
  console.log('Selecting by ID took '+idDuration+' milliseconds total over '+idTests+' tests.');
  console.log('Selecting by class took '+classDuration+' milliseconds total over '+classTests+' tests.');
  console.log('---');
  console.log('Average time for ID selection using $(\'#parentID .childClassName\') was: ' + (idDuration / idTests)+" milliseconds")
  console.log('Average time for class selection using $(\'.className\') was: ' + (classDuration / classTests)+" milliseconds")


})

【讨论】:

    【解决方案2】:

    我可能已经回答了我自己的问题。我创建了一个 jsperf,但我会重视更多的测试数据或改进。

    http://jsperf.com/should-we-always-descend-by-an-id/6

    编辑:在我的测试用例中,当您不从 id 下降时,jQuery 实际上更快,但明显的性能赢家(跨浏览器)是 document.getElementsByClassName()

    【讨论】:

    • 该测试可能存在缺陷,因为 jQuery 可能不使用 querySelector 在现代浏览器中按类名获取元素。 (但使用上述方法的测试似乎并不想在 jsperf 中正确运行......)
    • 和前面的评论也取决于使用的jQuery版本(1.x vs 2.x/3.x)
    猜你喜欢
    • 2016-12-17
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-01-27
    • 2011-04-21
    相关资源
    最近更新 更多