为什么jQuery选择器函数与原生DOM方法相比如此缓慢

Why is jQuery selector function so slow compared to native DOM methods

本文关键字:缓慢 方法 DOM 选择器 jQuery 函数 原生 为什么      更新时间:2024-04-15

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

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

我希望弄清楚为什么结果会是这样。

以下是测试:http://jsperf.com/jqueryspeed

最值得注意的是,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倍…

有什么想法吗?

这是当我们使用简单的$('selector')时,jquery所经过的代码量

http://james.padolsey.com/jquery/#v=1.10.2&fn=初始化

正如你所看到的,有很多验证,正则表达式匹配,跨浏览器技巧等。

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

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

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可以提高整体性能。

我为jQuery.fn.init(document.getElementById('id'))添加了另一个测试用例,它比大多数其他方法都快,因为它既不解析字符串,也不创建新的jQuery对象(它大约落后于getElementById、jsperf的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操作方面做得很好。