Daily-Interview-Question
Daily-Interview-Question copied to clipboard
第 72 题:为什么普通 for 循环的性能远远高于 forEach 的性能,请解释其中的原因
-
for 循环没有任何额外的函数调用栈和上下文;
-
forEach函数签名实际上是
array.forEach(function(currentValue, index, arr), thisValue)
它不是普通的 for 循环的语法糖,还有诸多参数和上下文需要在执行的时候考虑进来,这里可能拖慢性能;
@yygmind 想问问题目中的截图,测试JS运行时间或者性能的网站,可以给个地址吗?
找了spec
其中forEach 里操作了toObject 以及判断是否终止循环条件比for loop 复杂一点。
@yygmind 想问问题目中的截图,测试JS运行时间或者性能的网站,可以给个地址吗?
https://jsperf.com/testing-foreach-vs-for-loop
这是地址是截图的测试地址: https://jsperf.com/foreach-compare-for
为哈我测试出来foreach更高呢 chrome版本越高 性能越好
牛逼
for循环本来就是最原始的循环方案 foreach是基于它封装的
为什么 forEach
的性能那么差,为什么还要有这个方法呢?难道就是为了方便?
为什么
forEach
的性能那么差,为什么还要有这个方法呢?难道就是为了方便?
@jjeejj 我理解是普通的业务需求没有那么大的数组,所以性能差距很小。 forEach写法较for简单一点。个人理解
@mm-bt 第一个测试我也是forEach稍微快一丝丝,记得以前看过说针对forEach的实现是改过的.. 也就是用底层实现的循环(forEach,map)比自己写for循环效率要好.. 当时我在浏览器里跑过测试发现的确是这样..(10万以内) 然而刚我又写了一遍类似的..单次的话..for循环是要慢一些..
我之前用浏览器的做的实验,现在改为 node
发现了不一样的结果
let arrs = new Array(100000);
console.time('for');
for (let i = 0; i < arrs.length; i++) {
};
console.timeEnd('for');
console.time('forEach');
arrs.forEach((arr) => {
});
console.timeEnd('forEach');
for: 2.263ms
forEach: 0.254ms
在10万这个级别下, forEach
的性能是 for
的十倍
for: 2.263ms
forEach: 0.254ms
在100万这个量级下, forEach
的性能是和for
的一致
for: 2.844ms
forEach: 2.652ms
在1000万级以上的量级上 , forEach
的性能远远低于for
的性能
for: 8.422ms
forEach: 30.328m
@mm-bt 我也是,一样的结果,记得以前看过针对forEach的实现是改过的..依稀记得,我在浏览器里跑循环测试时间很多情况下forEach在数量非常大的情况下,比单纯的for要快一些...map也比for快,至少在10万次循环以内是这样
我也是,单独跑时间的话,是 forEach 快些,但是用那些性能测试工具的话,就是 for性能更好 比如 http://jsbench.github.io/ 和 https://jsperf.com/ 这两个工具测试
@jjeejj 看了你后面的时间测试结果,和我以前测得结果类似..你可以再加上map,10万以内map也会快一些.. 今天,我又查了下,发现,测试工具测试的是多次的结果...单次来看的确是forEach快..但是连着执行就会出现问题..10万以内的量级 连续执行10次就会有一倍的差距展示出来.. 期待有大佬能解答,为什么会这样,以及循环的这几个阈值是怎么来的..为什么.. 参考: 别人验证的文章 别人验证的文章2 v8的建议
var number = 100000;//array大小
var iteranum = 10;//迭代次数
var array = [];
for(let i=0;i<number;i++)
{
array[i] = i+1;
}
//test cicle
var len = array.length;
//正常for循环
console.time('normal for');
for(let k=0;k<iteranum;k++)
{
for(let i=0;i<len;i++)
{
array[i]+1;
}
}
console.timeEnd('normal for');
//倒序for循环
console.time('reverse for');
for(let k=0;k<iteranum;k++)
{
for(let i=len-1;i--;)
{
array[i]+1;
}
}
console.timeEnd('reverse for');
//while循环
console.time('while');
for(let k=0;k<iteranum;k++)
{
let i=0;
while(i<len)
{
array[i]+1;
i++;
}
}
console.timeEnd('while');
//for-in循环
console.time('for-in');
for(let k=0;k<iteranum;k++)
{
for(let i in array)
{
array[i]+1;
}
}
console.timeEnd('for-in');
//for each 循环
console.time("for each");
for(let k=0;k<iteranum;k++)
{
array.forEach(function(e){
e+1;
});
}
console.timeEnd("for each");
//map 循环
console.time("map");
for(let k=0;k<iteranum;k++)
{
array.map(function(e){
e+1;
});
}
console.timeEnd("map");
@jjeejj 看到过一个说法,forEach能让代码更为简便和可读性更高,在性能不是特别影响的前提下,代码的可拓展性,可读性等会更为重要,而且随着浏览器引擎的升级,应该forEach的性能会被优化的越来越棒的
简单去看,就是手动控制循环次数,和方法判定结束,肯定是不一样的
for循环是常见的循环语句forEach和map是在ES5出的,但是在性能上后者不如前者,在次数少的情况下forEach会比for要快,但是到达了十万次时forEach明显就跟不上了。在大数据量的情况下for循环的兼容性和多环境运行表现比较优秀,forEach的优点是在数据量小时占优势,语义话更简洁。循环时没有返回值。map和forEach差不多但是map循环有返回值
在chrome浏览器上测了一下,当数组length超过3355443时,forEach的耗时是超过for循环的
一个是判断数组的长度,一个是 判断对象的长度,还有判断对象里面有没有数组下标这个key, 类似于 list 跟 map。
我猜forEach需要的额外内存使得重复实验时触发了垃圾回收,因此稍慢于for
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
你这个测试里forEach函数里的方法应该是一次都没被调用过 所以执行时间较短
for循环是底层写法,效率高。 forEach是封装写法,效率会低一些 `let arrs = new Array(1000000); console.time('forEach'); arrs.forEach((arr) => {}); console.timeEnd('forEach');
console.time('for'); for (let i = 0,len=arrs.length; i < len; i++) {}; console.timeEnd('for');` 结果: forEach: 7.42919921875ms for: 4.7470703125ms
@jjeejj 看到过一个说法,forEach能让代码更为简便和可读性更高,在性能不是特别影响的前提下,代码的可拓展性,可读性等会更为重要,而且随着浏览器引擎的升级,应该forEach的性能会被优化的越来越棒的
可读性确实很重要,另外函数式编程也是趋势。
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
其实你这个测试方法有点小问题,for循环这样写会影响性能的,for (let i = 0; i < arrs.length; i++)每次循环都会计算arrs的长度,你可以改成for (let i = 0, let len = arrs.length; i < len; i++)再试一下。
v8 新版本其实现在性能上已经差不多了。但是forEach需要额外的内存和函数调用。不过新版本得v8给优化了。
@yygmind 想问问题目中的截图,测试JS运行时间或者性能的网站,可以给个地址吗?
https://jsperf.com/
foreach效率比for低主要分2个角度说。 2个地方,一个是.net 1.1之前的对值类型的装箱,一个是每次调用GetEnumator方法的函数调用带来的时间消耗,单一次都不消耗时间,但经过大量循环放大后,时间消耗比较明显。 .net 1.1之后的版本,foreach对值类型已经不装箱,不慢了,因为有了yield关键字。 但函数调用带来的堆栈创建内存分配则不可避免。 绝对意义上,for比foreach快,但从.net 1.1之后,这个差距缩小到多一层函数调用而已,不是特别严格的地方,还是用foreach好一点。因为foreach不止可以访问一个数组或List这样循环时能确定长度的集合,也可以访问可迭代的类型,对于一些不需要最开始就确定长度的,这样甚至效率更高,因为不需要在循环开始之前就准备好要循环的数据,而是每次foreach循环获取下一个数据。 其实也不用记什么情况用,多写写程序,应该不难区分用途 借鉴大佬https://me.csdn.net/wuyazhe
对于一些不需要最开始就确定长度的,这样甚至效率更高,因为不需要在循环开始之前就准备好要循环的数据,而是每次foreach循环获取下一个数据。 其实也不用记什么情况用,多写写程序,应该不难区分用
我咋觉得哥们走错片场了
为什么
forEach
的性能那么差,为什么还要有这个方法呢?难道就是为了方便?
forEach是声明式函数,我们不用关心内部如何去实现的;for循环是命令式函数,我们告诉计算器如何去做
foreach 循环性能1000000下不差吧
------------------ 原始邮件 ------------------ 发件人: "冰洋Zz"<[email protected]>; 发送时间: 2020年1月12日(星期天) 晚上11:26 收件人: "Advanced-Frontend/Daily-Interview-Question"<[email protected]>; 抄送: "杭州电子科技大学-胡大昌"<[email protected]>;"Comment"<[email protected]>; 主题: Re: [Advanced-Frontend/Daily-Interview-Question] 第 72 题:为什么普通 for 循环的性能远远高于 forEach 的性能,请解释其中的原因 (#121)
为什么 forEach 的性能那么差,为什么还要有这个方法呢?难道就是为了方便?
forEach是声明式函数,我们不用关心内部如何去实现的;for循环是命令式函数,我们告诉计算器如何去做
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or unsubscribe.
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
其实你这个测试方法有点小问题,for循环这样写会影响性能的,for (let i = 0; i < arrs.length; i++)每次循环都会计算arrs的长度,你可以改成for (let i = 0, let len = arrs.length; i < len; i++)再试一下。
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
其实你这个测试方法有点小问题,for循环这样写会影响性能的,for (let i = 0; i < arrs.length; i++)每次循环都会计算arrs的长度,你可以改成for (let i = 0, let len = arrs.length; i < len; i++)再试一下。 这种比较可能无法说明问题
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
其实你这个测试方法有点小问题,for循环这样写会影响性能的,for (let i = 0; i < arrs.length; i++)每次循环都会计算arrs的长度,你可以改成for (let i = 0, let len = arrs.length; i < len; i++)再试一下。
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
其实你这个测试方法有点小问题,for循环这样写会影响性能的,for (let i = 0; i < arrs.length; i++)每次循环都会计算arrs的长度,你可以改成for (let i = 0, let len = arrs.length; i < len; i++)再试一下。 这种比较可能无法说明问题
在chrome v8 6.x以后。对forEach的实现进行了改变。目前在v8 6.x forEach和for性能是一样的
- 问题不成立,没有谁远高于谁;
- 最高票的测试代码有问题: new Array(N).forEach压根不循环; i < arr.length如果大循环应该提前定义长度变量;
加一 10万以下 性能差不多
10万以上for性能秒杀foreach
找了spec
其中forEach 里操作了toObject 以及判断是否终止循环条件比for loop 复杂一点。
forEach不能终止循环, 何来判断条件一说
既然foreach没法终止(try catch)。没有for循环性能好,为啥大家大家还用呢
对于高票的答案稍微改造了下, 上面有同学提出 new Array(N) 对于forEach来讲是不会循环的. 所以改造了下 数组的创建方式. 另外for循环中也做了些改造. 现在的测试结果基本就很明显了.
10万次循环的对比结果:
let arrs = Array.from({length: 100000});
console.time('for');
let len = arrs.length;
for (let i = 0; i < len; i++) {
};
console.timeEnd('for');
console.time('forEach');
arrs.forEach((arr) => {
});
console.timeEnd('forEach');
for: 2.68310546875ms
forEach: 2.286376953125ms
100万次的对比结果
for: 2.40771484375ms
forEach: 15.508056640625ms
1000万次的对比结果
for: 7.268798828125ms
forEach: 153.18212890625ms
为什么普通 for 循环的性能远远高于 forEach 的性能,请解释其中的原因
- forEach需要额外的内存和函数调用,上下文作用域等等,所以会拖慢性能
- 新版浏览器已经优化的越来越好,性能上的差异会越来越小
为什么普通 for 循环的性能远远高于 forEach 的性能,请解释其中的原因
- forEach需要额外的内存和函数调用,上下文作用域等等,所以会拖慢性能
- 新版浏览器已经优化的越来越好,性能上的差异会越来越小
赛高!
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
如果按照之前的方法测试确实如此,不过给数组填充内容后,10万的数据量结果相差甚微,在100万数据量for循环大于forEach
let arrs = new Array(100000).fill(1);
console.time('for');
let for1 = []
for (let i = 0; i < arrs.length; i++) {
for1.push(arrs[i])
};
console.timeEnd('for');
console.time('forEach');
let for2 = []
arrs.forEach((arr, index) => {
for2.push(arr)
});
console.timeEnd('forEach');
for: 2.760986328125 ms
forEach: 2.88427734375 ms
在 node 和浏览器环境下,小于百万级的数据遍历,我这边测出来的结果始终是 forEach 优于 for
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
其实你这个测试方法有点小问题,for循环这样写会影响性能的,for (let i = 0; i < arrs.length; i++)每次循环都会计算arrs的长度,你可以改成for (let i = 0, let len = arrs.length; i < len; i++)再试一下。
一样的 不管是先赋值还是直接判断length都是上面的结论。 甚至在一千万时赋值length比直接判断耗时更长, 有点搞不懂
我之前用浏览器的做的实验,现在改为
node
发现了不一样的结果let arrs = new Array(100000); console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for'); console.time('forEach'); arrs.forEach((arr) => { }); console.timeEnd('forEach'); for: 2.263ms forEach: 0.254ms
在10万这个级别下,
forEach
的性能是for
的十倍for: 2.263ms forEach: 0.254ms
在100万这个量级下,
forEach
的性能是和for
的一致for: 2.844ms forEach: 2.652ms
在1000万级以上的量级上 ,
forEach
的性能远远低于for
的性能for: 8.422ms forEach: 30.328m
如果 使用 new Array(100000).fill(1)
,会发现,两者的差距并不大
当仅仅是 new Array(100000)
时, forEach 并不会执行 callback
这个问题有点问题,Chrome环境for比forEach快、Safari两种方式差异不明显、node环境forEach比for快
let arrs = new Array(100000); for (let i = 0; i < arrs.length; i++) { arrs[i] = i }; console.time('for'); for (let i = 0; i < arrs.length; i++) { }; console.timeEnd('for');
console.time('forEach');
arrs.forEach((arr) => {
}); console.timeEnd('forEach');
for: 1ms forEach: 2ms 奇怪我把楼上的代码复制一下,改了改 时间久是 for效率更好了 而且 有值的for循环比无值的for 速度更快