jQueryselect器$('#foo a')是如何评估的?
作为jQuery代码的一个例子( https://coderwall.com/p/7uchvg ),我读到了expression式$('#foo a');
performance如下:
find页面中的每
a
,然后过滤里面的#foo
。
而且看起来效率不高。
那是对的吗? 如果是的话,我们应该如何更好地做到这一点?
这是正确的 – Sizzle(jQuery的select器引擎)的行为方式与CSSselect器相同 。 CSS和Sizzleselect器从右到左进行评估 ,因此#foo a
将查找所有节点,然后从#foo
a
节点进行过滤。
通过确保您的叶子select器具有高度特异性,通常通过给他们一个类或ID,可以改善这一点。
我们应该如何更好地做到这一点?
使用jQuery中的上下文参数。
$('a', '#foo');
现在,jQuery将使用id:foosearch元素上下文中的所有锚点。
在您的查询中,上下文在省略时默认为文档:
$('#foo a'); == $('#foo a', document);
在这种情况下,您的查询的确效率不高。
你可以看看这篇文章 。
虽然Sizzle是一个从右到左的引擎(这与css被解释的方式相同),但是你的例子中的特定select器会select页面上的所有锚点元素,然后过滤它们的父元素到匹配“foo”的id。 Sizzle实际上优化了任何以ID开头的select器,并将其用作整个select的上下文,而不是使用文档。 换句话说,你select的select器基本上转化为:
document.getElementById("foo").getElementsByTagName("a")
真的,这不是一个糟糕的select。
但是,鉴于jQuery需要做的其他事情(包括循环元素以将它们合并到jQuery实例),jQuery(“#foo”)。find(“a”)总是最快的,因为jQuery实现了一个jQuery对象创build快捷方式为id-onlyselect器,然后它执行从#foo的根发现。
换句话说,当Sizzle("#foo a")
和Sizzle("a", document.getElementById("foo"))
,但是jQuery("#foo").find...
,Sizzle本身并没有太大的区别jQuery("#foo").find...
由于jQuery自己的ID快捷方式会更快。
顺便说一句,我对Sizzle的评论是假设querySelectorAll没有被使用。 如果是这样的话,Sizzle只是把它传递给qsa,这还不如使用jQuery的ID快捷方式。
您可以使用find()来更精细地控制select器顺序:
$('#foo').find('a');
这当然会更复杂的select器,你可以连锁find()和filter()。
对于logging$('#foo').find('a') === $('a','#foo')
[更新]好吧,我后来意识到,这正是你的链接说…
jQueryselect器引擎(Sizzle)去年已被重构,你会在这里find详细的解释: http : //www.wordsbyf.at/2011/11/23/selectors-selectoring/
而不是用a
里面的#foo
元素进行过滤,只需将一个类附加到a
元素上,并获得a
像$("a.class");
类a
元素$("a.class");
。 这会更有效率。
又一个“自己尝试”:
- jsperf用于10000个元素上的各种select器
- jsperf在300个元素上的各种select器
- jsperf为“更具代表性的DOM”上的各种select器
与“扁平”DOM(1&2)似乎没有太大的区别,但是嵌套的DOM性能差别更大。
还要注意一些testing用例没有select正确的元素(例如$('.a')
vs $('.a', context)
),但是为了比较,我将它们从原始testing中留下。
这个例子将检索名为foo
的元素中的所有锚点元素a
,在页面中查找每个a元素,然后筛选里面的#foo,如果您想要selecta #foo
$("a #foo");
这将检索元素内a
所有foo
元素。