Javascript 为什么jQuery选择器函数与本机DOM方法相比速度如此之慢

Javascript 为什么jQuery选择器函数与本机DOM方法相比速度如此之慢,javascript,jquery,performance,dom,getelementbyid,Javascript,Jquery,Performance,Dom,Getelementbyid,我知道这个话题已经被讨论过好几次了,但我正在寻找一个更技术和更详细的见解来理解到底发生了什么 我设计了一系列测试来比较jQuery最基本的选择器“#id”和“.class”与各种本机DOM方法的速度 我希望能弄清楚为什么会有这样的结果 以下是测试: 值得注意的是,getElementById显然是最快的。 为了比较,我添加了jQuery('#id')和jQuery.fn.init('#id')作为测试,两者之间的区别在于第一个确实实例化了一个全新的jQuery对象,而第二个只运行原型函数,因此速

我知道这个话题已经被讨论过好几次了,但我正在寻找一个更技术和更详细的见解来理解到底发生了什么

我设计了一系列测试来比较jQuery最基本的选择器“#id”和“.class”与各种本机DOM方法的速度

我希望能弄清楚为什么会有这样的结果

以下是测试:

值得注意的是,getElementById显然是最快的。 为了比较,我添加了jQuery('#id')和jQuery.fn.init('#id')作为测试,两者之间的区别在于第一个确实实例化了一个全新的jQuery对象,而第二个只运行原型函数,因此速度更快。因此,这两者之间的区别是可以理解的

然而,我不理解的主要区别是getElementById的速度与jQuery.fn.init的速度之间存在巨大的差距,jQuery.fn.init有一个简单的测试,可以以特定的方式处理简单的(“#id”)请求,返回到对getElementById本身的调用

那么,为什么举例来说,在Chrome上,这个方法比本地方法慢8倍,即使它基本上只是它的一个包装器

它也比包装的getElementById$(document.getElementById('#id'))慢3-4倍左右


有什么想法吗

jQuery没有什么比原生javascript做得更快,这是有原因的:它很难使代码跨浏览器兼容且易于使用。它使用大多数方法调用构建jQuery对象。在这方面,jQuery将比所需的最小数据路径慢得多,因为它希望提供可以随时使用的特性

让我们比较一下这两个“相似”的调用:

document.getElementById(“box”)
:本机方法,在低于JavaScript的级别上执行简单的查找操作。然后返回已经加载到内存中的DOM元素。这是最快的方法之一

$(“#box”)
:在这里,jQuery将从解析您要求它做的事情开始。例如,它将验证它是否是格式良好的选择器,然后尝试识别它是什么类型的选择器。验证完成后,它将尝试获取ID为“box”的元素。然后,他将创建一个新的jQuery对象,用每个期望的属性填充它,并确保所有浏览器(以及旧浏览器)都得到相同的结果。这包括许多回退和遵从性测试。当对象准备好使用时,您将获得ID为“box”的元素。不像
getElementById()
那样简单。当目标元素不需要jQuery功能时,许多人更喜欢使用
getElementById('box')
而不是
$('box')


更新-2017年2月15日:


由于jQuery>=2.0不再支持臭名昭著的IE 6/7/8,因此不再需要进行一些兼容性测试,从而使jQuery更轻巧、更快。如果您不需要支持较旧的浏览器,使用jQuery>=2.0而不是1.x可以提高总体性能。

这是使用简单的$('selector')时jQuery所需的代码量。

正如您所看到的,已经完成了大量的验证、正则表达式匹配、跨浏览器技巧等

重要的是要认识到jquery是一个基于javascript的库。javascript直接在浏览器上执行。而jquery在被浏览器执行之前会处理相当多的javascript代码


我个人更喜欢jquery。我真的不在乎节省那些纳秒。jquery提供的简单程度是惊人的,而且本身就是一件艺术品。

我为
jquery.fn.init(document.getElementById('id')添加了另一个测试用例
它比大多数其他方法都快,因为它既不解析字符串也不创建新的jQuery对象(它大约比getElementById落后50%),当我看到在调用
jQuery.fn.init期间执行的jQuery代码源时:

function (selector, context, rootjQuery){
  if (selector.nodeType) {
          this.context = this[0] = selector;
          this.length = 1;
          return this;
  }
}

我只能得出结论,Chrome和Firefox工程师在优化本机DOM操作方面做得非常好。

本机方法得到了高度优化,
$.fn.init
不仅仅是
document.getElementById
的“包装器”。那么为什么会出现速度差异呢?它不仅仅是一个包装器,它还有一个特殊的测试分支,最终只需调用getElementById。我并不惊讶有一个开销,但开销是如此之大!getElementById
的速度非常快(特别是在现代浏览器中)。因此,无论是什么开销,都将是
$.fn.init
的一小部分。如果您浏览代码,您将看到需要执行的操作。显然,这些操作没有得到优化和/或只是天生的较慢任务。与“轻任务加其他重任务”相比,这是“轻任务”。仅供参考,我增加了两个测试。一个只是
getElementById
的薄型包装。另一个是薄薄的包装,上面有一些安全检查。它们几乎和直接调用本机方法一样快。用户喜欢网站的速度;)这就是为什么我的jQuery免费站点在半秒内加载比我的竞争对手更受欢迎的原因,我的竞争对手使用jQuery,加载需要5秒以上的时间:3这是一个非常详细的解释,但有点离题。一旦调用$('#box'),jquery唯一要做的就是匹配一个正则表达式,然后测试匹配的一个项,然后转到一个特殊的区块,处理您只请求ID的情况。在这个简单的路径中没有关于浏览器合规性或其他内容的任何内容…@NiettheDarkAbsol客户喜欢jQuery等,因为他们可以花更少的钱获得更多的功能;)我们都希望每个客户都有一个infini