首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >jQuery.grep与Array.filter的性能

jQuery.grep与Array.filter的性能
EN

Stack Overflow用户
提问于 2013-02-01 13:34:36
回答 5查看 22.6K关注 0票数 39

问题中,讨论了jQuery和原生JS如何相互对抗。

当然,香草解决方案的执行速度要快得多,因为它没有处理整个数组,我建议使用Array.filter,我很有信心至少会比$.grep更快。

令人惊讶的是,在将它添加到测试中之后,我得到了一个教训:测试套件

当然,Edgecases有一个不同的结果。

任何知道为什么$.grep应该比本机方法Arrray.filter快3倍以上的人

编辑:我修改了测试以使用MDN过滤垫片,结果非常有趣:

  • Chrome:甚至MDN shim也比本机方法快,jQuery遥遥领先。
  • 火狐: shim比本地方法慢一点,jQuery遥遥领先

最后的结果就像我希望看到的

  • :本地方法是最快的,然后是jQuery,shim是最慢的(也许这只是IEs相当弱的JS引擎的结果.)
EN

回答 5

Stack Overflow用户

发布于 2013-02-01 13:39:17

正如在这篇博客文章上所发现的那样(它也进行相同类型的测试):

如果您阅读了filter的文档,您将看到为什么它要慢得多。

  1. 它忽略已删除的值和数组中的空白。
  2. 它还可以选择设置谓词函数的执行上下文。
  3. 它防止谓词函数对数据进行变异。
票数 17
EN

Stack Overflow用户

发布于 2013-02-01 14:13:16

ECMAScript 5.1规范15.4.4.20节Array.prototype.filter(callbackfn, thisArg)定义如下:

callbackfn应该是一个函数,它接受三个参数,并返回一个可以强制传递给布尔值truefalse的值。filter按升序对数组中的每个元素调用一次callbackfn,并为callbackfn返回true的所有值构造一个新数组。callbackfn只对实际存在的数组元素调用,而不对数组中缺少的元素调用。 如果提供了thisArg参数,则它将用作每次调用callbackfnthis值。如果不提供,则使用undefined。 使用三个参数调用callbackfn:元素的值、元素的索引和正在遍历的对象。 filter不会直接更改调用对象,但是对象可能会通过对callbackfn的调用而发生变异。 过滤器处理的元素范围是在第一次调用callbackfn之前设置的。在调用筛选开始后追加到数组中的元素将不会被callbackfn访问。如果更改了数组的现有元素,则传递给callbackfn的值将是筛选器访问它们的值;在调用筛选开始后和被访问之前被删除的元素不会被访问。

这本身就已经是很多工作;ECMAScript引擎需要执行的许多步骤。

然后,它接着说:

当使用一个或两个参数调用filter方法时,将执行以下步骤: 让O是调用ToObject作为参数传递this值的结果。让lenValue是使用参数length调用O[[Get]]内部方法的结果。让len成为ToUint32(lenValue)。如果IsCallable(callbackfn)为false,则引发TypeError异常。如果提供了thisArg,则将T设为thisArg;否则将T定义为未定义。让A是一个新数组,好像是通过表达式new ()创建的,其中array是具有该名称的标准内置构造函数。让k是0。让它变成0。重复,而k< len让Pk为ToString(k)。让kPresent是调用带有参数Pk的O的[HasProperty]内部方法的结果。如果kPresent是真的,那么让kValue是调用带有参数Pk的O的[Get]内部方法的结果。假设selected是调用回调的[ Call ]内部方法的结果,以T作为包含kValue、k和O的值和参数列表。如果ToBoolean(selected)为真,则调用带有参数ToString(to)的A的[DefineOwnProperty]内部方法、属性描述符{[ value ]:kValue、[Writable]:true、[枚举]:true、[Configurable]:true}和false。增加到1。将k增加1。返回A。 滤波器方法的长度属性为1。 注意,filter函数是有意泛型的;它不要求它的这个值是Array对象。因此,它可以转移到其他类型的对象作为一种方法。过滤器函数能否成功地应用于宿主对象是取决于实现的。

有关此算法的一些需要注意的事项:

  • 它防止谓词函数对数据进行变异。
  • 它还可以选择设置谓词函数的执行上下文。
  • 它忽略已删除的值和数组中的空白。

在很多情况下,这些东西都不需要。因此,在编写自己的filter方法时,大多数情况下您甚至都不会去执行这些步骤。

每个符合ES5.1标准的JavaScript引擎都必须符合该算法,因此每次使用Array#filter时都必须执行所有这些步骤。

毫不奇怪,任何只执行这些步骤的一部分的自定义编写方法都会更快:)

如果您编写自己的filter函数,很可能它不会像上面的算法那样复杂。也许您根本不需要将数组转换为对象,因为根据用例的不同,可能不需要仅用于筛选数组。

票数 8
EN

Stack Overflow用户

发布于 2013-02-14 18:28:21

我发现了一些有趣的东西。正如MarcoK所解释的那样,$.grep只是一个带有for循环的简单实现。在大多数情况下,过滤器速度较慢,因此实现必须不同。我想我找到了答案:

代码语言:javascript
复制
function seak (e) { return e === 3; }

var array = [1,2,3,4,5,6,7,8,9,0], i, before;
array[10000] = 20; // This makes it slow, $.grep now has to iterate 10000 times.
before = new Date();

// Perform natively a couple of times.
for(i=0;i<10000;i++){
    array.filter(seak);
}

document.write('<div>took: ' + (new Date() - before) + '</div>'); // took: 8515 ms (8s)

before = new Date();

// Perform with JQuery a couple of times
for(i=0;i<10000;i++){
    $.grep(array, seak);
}
document.write('<div>took: ' + (new Date() - before) + '</div>'); // took: 51790 ms  (51s)

本机“过滤器”在这种情况下要快得多。所以我认为它迭代属性而不是数组索引。

现在让我们回到‘大’问题;)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14647470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档