javascript中forEach,map,for of的应用场景与效率?

这裡讨论的是lodash版本的_.forEach和_.map,原生ES6 javascript的for of这三种方法。
目前我的使用思路是,如果是要遍历并改变Array并回传一个新的Array,那我就选择_.map。

至于for of 和_.forEach,我用了以下的方式测试效能:

forEach

let arr = [];
for(var i = 0 ; i<50000000 ; i++){
    arr.push(i);
}
var start = Date.now();
let sum = 0;
_.forEach(arr,(a)=>{
    sum += a;
});
var end = Date.now();
console.log('总数:'+sum,'毫秒数:'+(end-start));
//总数:1249999975000000 毫秒数:1530

for of

let arr = [];
for(var i = 0 ; i<50000000 ; i++){
  arr.push(i);
}
var start = Date.now();
let sum = 0;
for(let a of arr){
  sum += a;
}
var end = Date.now();
console.log('总数:'+sum,'毫秒数:'+(end-start));
//总数:1249999975000000 毫秒数:575

for of速度大胜_.forEach,所以在遍历Array时,我现在会使用for of而不是_.forEach。

我想问的是,这样的思路有问题吗?
_.forEach要在什麽时候使用呢?

我自己想到的_.forEach使用时机是遍历Object时,javascript原生的话应该是和for in比较。

阅读 7.1k
4 个回答

有问题。
JS中不存在传统意义上的数组,静态语言中,数组是一段连续的内存,每一个元素都是固定字节长度的,所以通过下标可以取地址,快速找到引用值。
但是JS中的数组是对象,这导致你遍历数组时,其实是在遍历对象的key(静态语言中的HashMap),而JS中对数组类型的遍历做了特殊处理,所以foreach遍历不到非数值类型的键,这也解释了为什么foreach比forin慢,因为多了一层判断。
但是如果你使用forin遍历数组,会带出非数字键:

var x = [1, 2, 3];
x.a = 'a';
x.b = 'b';
x.c = 'c';
for (let k in x)
  console.log(k)

即使你不会这么干,谁知道你的同伴们呢?第三方框架中呢?自定义原型链呢?

结论:ES5中遍历数组还是老老实实的foreach或者for循环.
你的例子中使用的是ES6,由于Array类型实现了Iterator接口,所以forof是安全的,但是如果通过babel编译成es5,我猜想由于需要引入Iterator的pollyfill,效率不可能比foreach高。

上面对比其实有一个很重要的因素要考虑进去:

_.forEachfor of 每次循环要多一个函数调用

在每次循环操作很简单的情况下(本例中就是个简单的数字相加赋值的操作),函数调用对整体的操作时间有很大的影响,造成了上面的时间差异将近 3 倍

我稍微改下题主的代码,在每次循环内增加点操作,效果如下:
clipboard.png

可以看到,两种方式的时间差基本在 1000ms 左右,原因就是上面说的 -- forEach 每次多一个函数调用

结论:for of 在很简单的操作下,效率明显优于 forEach,如果题主在意效率的话,就用 for of (或者为了兼容用 for 循环)

ps: 我其实一直用的 forEach,因为写起来方便,平时 for 循环的长度 1000+ 都算大的了,感觉这点效率问题完全可以忽略,不要过度优化。

Loadash 不是跟 jQuery 作用差不多么,就是为了兼容各个环境,统一 API

所以当然是浏览器原生实现效率高啊

如果你不需要兼容老浏览器,肯定直接 ES6+

上面各位答主说了不少了,但是还有一个差异,for of 可以使用 continuebreakforEach 不行。

在遍历数组的循环里,除了原生 forfor of,其他循环都不行。

for in 我印象里记得可以,但它不是遍历数组的。

所以如果需要跳过或跳出,又不想使用原生 for 循环,那么使用 for of 是极好的。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题