jQuery 选择器的性能
Performance of jQuery selector
这个选择器是:
$("div#myId")
比这个选择器更快:
$("#myId")
?
两者都很好,但我想提高性能。
根据 jsperf,$("#myId")
比 $("div#myId")
.
~4 倍
使用 id 值时,您添加到选择器的任何其他内容都不会提高性能。浏览器已经有了所有 id 值的索引,因为文档中的所有 id 都应该是唯一的。向选择器添加其他东西只会使它必须测试的东西更多。例如,对于 #myId
,可以使用对 document.getElementById("myId")
的短路,但在 div#myId
、jQuery 或其调用的函数必须首先将选择器解析为它的件,找到具有正确 ID 的对象,然后检查它是否也是 div
.
如果你真的想绝对确定地知道任何两种情况之间的性能差异,那么你必须编写性能测试(在像 http://jsperf.com 这样的工具中并在所有相关浏览器中测试它。
一般来说,您应该遵循使用最简单的代码以适当的性能完成工作的公理。那可能是 $("#myId")
除非你真的想优化纯性能,在这种情况下你会使用 document.getElementById("myId")
.
而且,对于 grins,jQuery 根本不快(它创建一个对象,运行s 一个构造函数,分析选择器,评估选择器,查看其他可能的选项passed, etc...), 所以如果你真的关心优化最大化性能,你就不会首先使用 jQuery 。也就是说,jQuery 大大加快了编写代码的时间,因此在很多情况下都是值得的。
请参阅 jsperf:http://jsperf.com/jqvsother 进行性能比较。
在Chrome中,三者的区别还是挺大的:
$("div#myId") - 446,589 ops/sec
$("#myId") - 1,705,994 ops/sec
document.getElementById("myId") - 32,278,617 ops/sec
因此,$("#myId")
比 $("div#myId")
快 4 倍,document.getElementById("myId")
比 $("#myId")
快 19 倍。这是一个比我预期的更大的差异。
这是一个图形表示(长条更快):
当你测量而不是猜测时,你总能学到一些东西。
深入研究 jQuery 选择器处理代码,您会看到:
- 检查是否传递了任何选择器。
- 检查它是否是一个字符串,是否看起来像 HTML
"<.....>"
- 如果看起来不像简单的 HTML,运行 这个
/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/
正则表达式就可以了
- 如果正则表达式显示选择器只是
"#xxxx"
,则调用 document.getElementById()
。
- 如果它看起来更复杂 HTML(可能带有属性),则将 HTML 处理成 DOM 个对象
- 如果没有这些特殊字符串中的任何一个,则运行
.find()
找到匹配的选择器。 运行 .find()
将选择器从要评估的 Sizzle 引擎传递出去(从头开始)。
- Sizzle 引擎然后 运行 选择器上的另一个正则表达式,再次寻找它可以选择更快方法的快捷方式。
- 最终,如果 none 的快捷方式通过并且选择器中没有特殊项目,则调用
querySelectorAll()
。
- 等等,处理其他可能要传递的非字符串的东西(DOM对象,jQuery对象等...)
所以,我从中得到了一些东西。首先,有一个简单的“#xxxx”字符串的快捷方式,可以避免很多其他处理。为什么这样更快也就不足为奇了。其次,任何避免进入最终调用 querySelectorAll()
的 Sizzle 选择器评估代码深处的捷径都会加快速度。
基于 http://learn.jquery.com/performance/optimize-selectors/#specificity 很高兴注意到 jQuery 从右到左读取选择器。
意味着如果你要写这样的东西 $("div#myId")
jQuery 将获取所有元素,匹配具有相同 ID 的元素(因为 ID 是唯一的,它应该停在这里)但是因为你还指定 div,jQuery 将继续并检查它是否是 div。这将使一项额外的工作成为不必要的。
因此,对于其他选择器,最好注意右侧比左侧更具体。
切勿在 id 之前添加标签名称,这会降低选择器的速度。
$('#content')
优于 $('div#content')
jQuery 开始使用正则表达式解析选择器。如果它透露选择器是一个 id,因为它以一个尖锐的 (#) 开头,在幕后 jQuery 将使用 JavaScript 原生的 getElementById() 方法,那是非常快的。
这个选择器是:
$("div#myId")
比这个选择器更快:
$("#myId")
? 两者都很好,但我想提高性能。
根据 jsperf,$("#myId")
比 $("div#myId")
.
使用 id 值时,您添加到选择器的任何其他内容都不会提高性能。浏览器已经有了所有 id 值的索引,因为文档中的所有 id 都应该是唯一的。向选择器添加其他东西只会使它必须测试的东西更多。例如,对于 #myId
,可以使用对 document.getElementById("myId")
的短路,但在 div#myId
、jQuery 或其调用的函数必须首先将选择器解析为它的件,找到具有正确 ID 的对象,然后检查它是否也是 div
.
如果你真的想绝对确定地知道任何两种情况之间的性能差异,那么你必须编写性能测试(在像 http://jsperf.com 这样的工具中并在所有相关浏览器中测试它。
一般来说,您应该遵循使用最简单的代码以适当的性能完成工作的公理。那可能是 $("#myId")
除非你真的想优化纯性能,在这种情况下你会使用 document.getElementById("myId")
.
而且,对于 grins,jQuery 根本不快(它创建一个对象,运行s 一个构造函数,分析选择器,评估选择器,查看其他可能的选项passed, etc...), 所以如果你真的关心优化最大化性能,你就不会首先使用 jQuery 。也就是说,jQuery 大大加快了编写代码的时间,因此在很多情况下都是值得的。
请参阅 jsperf:http://jsperf.com/jqvsother 进行性能比较。
在Chrome中,三者的区别还是挺大的:
$("div#myId") - 446,589 ops/sec
$("#myId") - 1,705,994 ops/sec
document.getElementById("myId") - 32,278,617 ops/sec
因此,$("#myId")
比 $("div#myId")
快 4 倍,document.getElementById("myId")
比 $("#myId")
快 19 倍。这是一个比我预期的更大的差异。
这是一个图形表示(长条更快):
当你测量而不是猜测时,你总能学到一些东西。
深入研究 jQuery 选择器处理代码,您会看到:
- 检查是否传递了任何选择器。
- 检查它是否是一个字符串,是否看起来像 HTML
"<.....>"
- 如果看起来不像简单的 HTML,运行 这个
/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/
正则表达式就可以了 - 如果正则表达式显示选择器只是
"#xxxx"
,则调用document.getElementById()
。 - 如果它看起来更复杂 HTML(可能带有属性),则将 HTML 处理成 DOM 个对象
- 如果没有这些特殊字符串中的任何一个,则运行
.find()
找到匹配的选择器。 运行.find()
将选择器从要评估的 Sizzle 引擎传递出去(从头开始)。 - Sizzle 引擎然后 运行 选择器上的另一个正则表达式,再次寻找它可以选择更快方法的快捷方式。
- 最终,如果 none 的快捷方式通过并且选择器中没有特殊项目,则调用
querySelectorAll()
。 - 等等,处理其他可能要传递的非字符串的东西(DOM对象,jQuery对象等...)
所以,我从中得到了一些东西。首先,有一个简单的“#xxxx”字符串的快捷方式,可以避免很多其他处理。为什么这样更快也就不足为奇了。其次,任何避免进入最终调用 querySelectorAll()
的 Sizzle 选择器评估代码深处的捷径都会加快速度。
基于 http://learn.jquery.com/performance/optimize-selectors/#specificity 很高兴注意到 jQuery 从右到左读取选择器。
意味着如果你要写这样的东西 $("div#myId")
jQuery 将获取所有元素,匹配具有相同 ID 的元素(因为 ID 是唯一的,它应该停在这里)但是因为你还指定 div,jQuery 将继续并检查它是否是 div。这将使一项额外的工作成为不必要的。
因此,对于其他选择器,最好注意右侧比左侧更具体。
切勿在 id 之前添加标签名称,这会降低选择器的速度。
$('#content')
优于 $('div#content')
jQuery 开始使用正则表达式解析选择器。如果它透露选择器是一个 id,因为它以一个尖锐的 (#) 开头,在幕后 jQuery 将使用 JavaScript 原生的 getElementById() 方法,那是非常快的。