在问题中,讨论了jQuery和原生JS如何相互对抗。
当然,香草解决方案的执行速度要快得多,因为它没有处理整个数组,我建议使用Array.filter,我很有信心至少会比$.grep更快。
令人惊讶的是,在将它添加到测试中之后,我得到了一个教训:测试套件
当然,Edgecases有一个不同的结果。
任何知道为什么$.grep应该比本机方法Arrray.filter快3倍以上的人
编辑:我修改了测试以使用MDN过滤垫片,结果非常有趣:
最后的结果就像我希望看到的
发布于 2013-02-01 13:39:17
正如在这篇博客文章上所发现的那样(它也进行相同类型的测试):
如果您阅读了
filter的文档,您将看到为什么它要慢得多。
发布于 2013-02-01 14:13:16
ECMAScript 5.1规范15.4.4.20节将Array.prototype.filter(callbackfn, thisArg)定义如下:
callbackfn应该是一个函数,它接受三个参数,并返回一个可以强制传递给布尔值true或false的值。filter按升序对数组中的每个元素调用一次callbackfn,并为callbackfn返回true的所有值构造一个新数组。callbackfn只对实际存在的数组元素调用,而不对数组中缺少的元素调用。 如果提供了thisArg参数,则它将用作每次调用callbackfn的this值。如果不提供,则使用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函数,很可能它不会像上面的算法那样复杂。也许您根本不需要将数组转换为对象,因为根据用例的不同,可能不需要仅用于筛选数组。
发布于 2013-02-14 18:28:21
我发现了一些有趣的东西。正如MarcoK所解释的那样,$.grep只是一个带有for循环的简单实现。在大多数情况下,过滤器速度较慢,因此实现必须不同。我想我找到了答案:
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)本机“过滤器”在这种情况下要快得多。所以我认为它迭代属性而不是数组索引。
现在让我们回到‘大’问题;)。
https://stackoverflow.com/questions/14647470
复制相似问题