Javascript 为什么使用for比some()或filter()更快
我尝试了两种不同的方法来做某事,我对性能结果感到惊讶: 我有两个版本的函数:Javascript 为什么使用for比some()或filter()更快,javascript,angularjs,performance,Javascript,Angularjs,Performance,我尝试了两种不同的方法来做某事,我对性能结果感到惊讶: 我有两个版本的函数: $scope.hasBlockResult = function (IS, area, block) { if (!block) return false; return ($scope.filteredCartoList.some(function (carto) { if (carto.informationSystem === IS && cart
$scope.hasBlockResult = function (IS, area, block) {
if (!block)
return false;
return ($scope.filteredCartoList.some(function (carto) {
if (carto.informationSystem === IS && carto.area === area && carto.block === block)
return true;
return false;
}));
};
对使用:
$scope.hasBlockResult = function (IS, area, block) {
if (!block)
return false;
for (var i = 0; i < $scope.filteredCartoList.length; i++) {
if ($scope.filteredCartoList[i].informationSystem === IS
&& $scope.filteredCartoList[i].area === area
&& $scope.filteredCartoList[i].block === block)
return true;
}
return false;
};
for (var i = 0; i < $scope.filteredCartoList.length; i++) {
if ($scope.filteredCartoList[i].informationSystem == IS
&& $scope.filteredCartoList[i].type != 'AM'
&& $scope.filteredCartoList[i].type != 'IF'
&& $scope.filteredCartoList[i].area == area
&& $scope.filteredCartoList[i].block == block)
$scope.resultList.push($scope.filteredCartoList[i]);
}
$scope.resultList = $scope.filteredCartoList.filter(function (carto) {
if (carto.informationSystem == IS
&& carto.type != 'AM'
&& carto.type != 'IF'
&& carto.area == area
&& carto.block == block)
return true;
return false;
});
这里也一样:
在
的之间:
$scope.hasBlockResult = function (IS, area, block) {
if (!block)
return false;
for (var i = 0; i < $scope.filteredCartoList.length; i++) {
if ($scope.filteredCartoList[i].informationSystem === IS
&& $scope.filteredCartoList[i].area === area
&& $scope.filteredCartoList[i].block === block)
return true;
}
return false;
};
for (var i = 0; i < $scope.filteredCartoList.length; i++) {
if ($scope.filteredCartoList[i].informationSystem == IS
&& $scope.filteredCartoList[i].type != 'AM'
&& $scope.filteredCartoList[i].type != 'IF'
&& $scope.filteredCartoList[i].area == area
&& $scope.filteredCartoList[i].block == block)
$scope.resultList.push($scope.filteredCartoList[i]);
}
$scope.resultList = $scope.filteredCartoList.filter(function (carto) {
if (carto.informationSystem == IS
&& carto.type != 'AM'
&& carto.type != 'IF'
&& carto.area == area
&& carto.block == block)
return true;
return false;
});
我期望filter()
和some()
方法比for
方法快,但根据angularjs batarang performance tab,在这两种情况下,for
的速度更快。考虑以下两个例子:
for (var i = 0; i < array.length; i++) {
doThing(array[i]);
}
for(变量i=0;i
vs
函数processItem(项目){
打点(项目);
}
对于(var i=0;i
这基本上就是两者的区别。filter
和some
中还必须有一些逻辑来处理来自processItem
的返回值,但基本上,您是在循环的顶部堆积一个完整的额外函数调用。在性能方面,没有什么比原生(普通)javascript更好的了。问题归结为“您是想花费时间和资源,通过自己动手来重新发明轮子,还是仅仅利用一个外部库来为您实现?”。是的,你牺牲了加载时间和性能,但你节省了时间,时间就是金钱。通过缓存数组的长度,可以加快for循环
for(变量i=0,len=$scope.filteredCartoList.length;i
这将更快地工作,尤其是在IE中,因为这里您正在缓存$scope.filteredCartoList的长度,而不是在循环的每个迭代中计算它。我查看了您在评论中发布的内容。这些基准有一些缺陷:
- 循环示例在基准本身中使用
console.timeEnd
和console.log
,这两种方法都很慢。在撰写本文时,其他例子都没有这样做
some
示例执行类型强制
- 所有测试都在其循环中执行字符串连接
为了从这些基准中得出任何结论,我们首先需要消除这些偏差来源
以下是8GB DDR3 i5笔记本电脑的结果,消除了这些偏差,按从最快到最慢的顺序重新排序(数字越小越好):
这些都是可以预期的,原因如下:
对象访问
对象访问非常快,因为对象本质上是散列映射。无论对象大小如何,访问元素的速度都是恒定的
寻找
Seek的实现方式是使用indexOf
定位元素,然后在直接数组索引中访问该元素。虽然实际的方法是特定于实现的,但它将非常类似于对象访问,因此速度非常快
环
循环方法的速度较慢,主要是因为与“seek”测试不同,循环测试迭代整个数组,并执行数组访问和对象访问。seek方法不能做到这一点。它几乎在找到元素后立即爆发
这意味着除了最坏的情况外,在所有情况下,seek都比loop快
一些
有些具有每次迭代都要调用的函数调用的开销。此外,JIT编译器根本无法对其进行优化,因为JIT编译器不知道您将向some
传递什么。在优化程度最高的情况下,有些函数最多只能执行与循环相同的操作,但由于函数调用的原因,执行速度总是较慢
滤器
过滤器具有“some”的所有警告,但它总是在整个数组中迭代,而不是在单个元素上停止。因此,您应该总是期望过滤器比for循环慢很多,特别是当您认为<代码>筛选器< /代码>也创建了一个新数组时,它返回了!p> 我想some和filter也必须循环通过filter()
应该和for
一样慢some()
在最坏的情况下,速度将与的一样慢。我不明白为什么你认为它们中的任何一个都应该比本地的更快,因为它们都在引擎盖下使用。@Dan Pantry:读了这篇文章后,我认为它会更优化:filter
迭代整个数组,所以就这样了some
如果在数组的早期遇到与谓词匹配的元素,则速度可能会更快,但如果没有找到与谓词匹配的元素,则也可以直接到达数组的长度。通过只迭代一次数组(即延迟执行),而不是像这样尝试微优化,您可能会看到更好的性能提高。首先,他在循环中执行console.log,而不是在其他地方。删除控制台日志和控制台时间结束会将循环时间降至0.005800000002030477
(从0.032693333188721
)。这样快了7倍。这最终使3倍快的过滤器和类似的速度,一些(虽然较慢)在我的机器上。这就是我希望看到的。对象访问和直接阵列访问都像预期的那样快得惊人,如果在阵列中更早地使用了some,那么一些会更快。那些测试都是垃圾。是的,我认为像filter
或some
这样的函数可能与for
不同,比如使用位比较或更深入的方法。这个答案没有意义,循环时间比过滤时间快3倍,你的解释是“循环迭代整个数组”,'过滤器迭代整个数组'????那么,为什么要慢3倍呢?一点也不回答这个问题all@RenaissanceProgrammer这个答案的一部分是不正确的(我现在就纠正它);过滤器迭代“整个”数组的部分是将其与some-Fil进行比较