为什么这段代码这么慢? 使用 Array.proto.reduce 的时候, 一定要复用 accumulator ?

2018-06-28 11:38:48 +08:00
 iugo
https://jsbin.com/ragisokawe/edit?js,console
2288 次点击
所在节点    程序员
14 条回复
autoxbc
2018-06-28 12:08:35 +08:00
是的,意识到这个后,我把自己代码里所有的 reduce 都改写了,尤其是展开再合并那种
VDimos
2018-06-28 12:14:42 +08:00
不推荐使用 reduce
Torpedo
2018-06-28 12:36:29 +08:00
test1,test1.2,test1.3 到后来每次循环都是把一个 成百上千的对象的属性赋值给一个新的对象,能不慢么。。。
qdwang
2018-06-28 12:43:35 +08:00
reduce 实力背锅
jimliang
2018-06-28 13:11:43 +08:00
老铁,你用法错了,无端端生成很多没用的对象
正确用法:
```
console.time('test3');
const dataMap33 = arr.reduce((acc, v) => {
acc[v.id] = v.name;
return acc;
}, Object.create(null));
console.timeEnd('test3');
```
UnluckyNinja
2018-06-28 17:09:41 +08:00
吃饭的时候,
吃一口,把筷子洗了,洗双新筷子,然后吃下一口,再洗掉,再换新的,
感受一下
iugo
2018-06-28 17:27:55 +08:00
@jimliang 我一般不会直接修改函数参数, 虽然这种风险是可控的. 可能 accumulator 是个例外.
Pastsong
2018-06-28 17:31:51 +08:00
因为 reduce 是 immutable 的
iugo
2018-06-28 17:38:44 +08:00
auroraccc
2018-06-28 17:58:13 +08:00
不是 reduce 的锅吧 , 主要是 ... 耗时
iugo
2018-06-28 18:00:23 +08:00
声明对象不可怕, 声明大对象是有点吓人.

对于标题, 我觉得结论可能是:

使用 Array.proto.reduce 的时候, 一定要复用 accumulator.
UnluckyNinja
2018-06-28 18:09:13 +08:00
@iugo #9 testFn 根本就没用到 testAcc ……只是每次循环对其赋值,只是执行了 1000 对长度为 1 的对象添加了一个属性而已……(你添加属性的方法是返回新变量)

你之前那个脚本问题在于对对象,你循环 n 次,每次都要对第 n-1 次循环的返回对象打散然后重组,相当于操作 n-1 次 Object.assign。也就是复杂度大约为 O(n^2),当然慢啦……
morethansean
2018-06-28 18:58:26 +08:00
这么多写操作……
而且光是 GC 的时间就比你第二种操作耗时多好多倍了……
iugo
2018-07-10 15:53:02 +08:00
关于使用 reduce 的时候是否要修改 acc 问题, 我想这个 issue 是值得参考的: https://github.com/eslint/eslint/issues/8581

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/466520

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX