Mootools Selectors $ 或 $$.哪个性能更高

Mootools Selectors $ or $$. Which is more performant

本文关键字:性能 Selectors Mootools      更新时间:2023-09-26

我很好奇浏览器查找哪个选择器会更快。我对一般浏览器而不是特定浏览器感兴趣。

$('accountDetailsTable').getElements('.toggler')

这将查找accountDetailsTable,就像您使用document.getElementById('accountDetailsTable');一样,然后在元素内部查找.toggler

$$('.toggler')

而这个将直接返回所有选择器。但最终他们都会给我相同的结果。

那么哪一个会更快呢?我该如何测试这个?

选择器的性能在浏览器之间会有很大差异。 例如,有querySelectorquerySelectorAll(QSA)与没有。当没有QSA时,有getElementsByClassName或没有。

选择器引擎需要执行的工作量会有所不同。

你可以用不同的方式写这个。 3 种方法,而不仅仅是 2 种:

1. $('accountDetailsTable').getElements('.toggler')

以上剖析为:

  • 获取元素(1 次调用)。
  • 从元素原型调用方法 getElements(或直接在旧 IE 中调用元素)
  • 查找与类选择器匹配的所有子节点

这在浏览器中是一致的,因为它会获取一个根节点并从中调用方法。 如果没有 QSA,它将转到getElementsByClassName或遍历所有childNodes并筛选 className 属性,直到它有一个匹配项列表。性能方面,这在现代浏览器中会更糟,因为它需要链接,而方法 3 将是直接结果。

由于选择器在 JS 中的工作方式,与 CSS 不同 - 它是从左到右的,更合格的选择器可以提高性能,具有类似 .toggler 意味着当有一个较旧的浏览器时,它不必要地需要考虑树中的每个 DOMnode(文本节点除外)。 始终尽可能限定选择器,即 div.togglera.toggler.

2. $$('.toggler')

  • 如果 QSA 可用,依靠浏览器返回内容(这里没有额外的黑客,如 :not:contains:has!(反向组合器)。
  • 如果没有 QSA,它将通过 Slick 解析器解析表达式,并且基本上在内部降级到类似于上述情况 1 的内容。这里最大的区别是缺乏上下文 - 它将针对整个文档运行,因为 $$ 在内部执行类似 document.getElements('.toggler') 的操作,因此需要考虑更多节点。始终将查询锚定到稳定的最上层常见节点。或将其传递到查询字符串中进行限定,如案例 3 所示

再一次,这将通过使其更合格来改善性能,例如:

$$('a.toggler')

3. $$('#accountDetailsTable .toggler')

  • 与情况 2 类似,但当 QSA 可用时,它会更快。
  • 当 QSA 不存在时,它将针对 #accountDetailsTable 节点的上下文运行,因此它将比情况 2 更好。

使其更合格将有所作为:

$$('#accountDetailsTable td.control > a.toggler')

大折扣:这取决于你的 DOM 有多大,找到并返回多少匹配项。 在简单的 DOM 上,预期的性能顺序可能会有所不同。

如今,选择器的性能优化越来越无关紧要。

SlickText比较框架的日子已经结束,应用程序性能与选择器速度无关,或者你做错了什么。

如果你的工作做得对,你就不需要不断地选择元素。您可以缓存内容,重用,变得聪明并将DOM查找减少到最低限度。

事件

等可以通过智能事件委派附加,在适当的情况下,完全不需要选择事件并将其添加到多个节点等 - 使用常识,不要被理论性能基准所困扰。相反,请使用探查器并测试您的实际应用程序,看看您在哪里浪费了时间/CPU 周期。

您可以在一秒钟内运行这样的简单选择器超过 50000 次。这是微基准测试,并不能衡量您的APP,DOM,浏览器等中的实际实际性能。

关于基准测试和过早优化的更多想法:http://www.youtube.com/watch?v=65-RbBwZQdU

小心

首先要写正确性和可读性。即使你可以通过做某事获得额外的性能,如果它不是关键的/一直重用的,也不要以牺牲可读性为代价。像.toggler.new.button等选择器往往过于通用,可以在DOM的不同部分的应用程序中重复使用。您需要限定选择器,以确保当您的预期功能移动到不同的页面/小部件/DOM并且您的项目涌入新开发人员时将继续工作。

只是我的两分钱,我知道你已经接受了答案。

在过去的两年里,我的内部MooTools知识变得有些生疏,但总的来说,我希望$$选择器要快得多,因为它只需要运行一次元素。

为什么不试一试呢?请参阅此 JSfiddle:

粗略的 HTML:

<div id="accountDetailsTable">
    <div id=".toggler">1</div>    
    <div id=".toggler">2</div>    
    <div id=".toggler">3</div>    
</div>

JScript(请不要评论糟糕的代码,它只是为了演示功能):

window.addEvent('domready', function() { 
    var iter = 50000;
    var tstart = new Date().getTime();
    for (var i=0;i<iter;i++) {
        var x = $('accountDetailsTable').getElements('.toggler');
    }
    var tend = new Date().getTime();   
    var tdur = tend - tstart;
    console.log('$: ' + tdur + ' ms');
    var tstart = new Date().getTime();
    for (var i=0;i<iter;i++) {
         var x = $$('.toggler');
    }
    var tend = new Date().getTime();   
    var tdur = tend - tstart;
    console.log('$$: ' + tdur + ' ms');
});

也就是说,我对大约 50000 次迭代的测试大致得出了以下结果:

  • $('accountDetailsTable').getElements('.toggler') : ~ 4秒
  • $$('.toggler') : ~ 2秒

结果会因浏览器、元素等而异,因此这只是一个粗略的近似值。

也就是说,如果您在如此短的时间内拥有这么多选择器,您可能会感到不同。是的,应该考虑性能,如果您的应用程序中只有几个选择器,那么这并不重要。

我更喜欢$$(),不是因为更好的性能,而是因为更好的可读性。