回顾reduce方法
reduce() 方法对数组中的每个元素按序执行一个由您提供的reducer函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
reduce()函数接受两个参数:
- reducer:回调函数
- initialValue:
reducer回调函数可以接受四个参数:
- pre:上一次调用
reducer的返回值,如果指定了initialValue,则第一次循环中pre为initialValue - cur:当前要遍历的数组元素
- index:当前遍历元素的下标
- array:当前遍历的数组
- 如果有
initialValue,则第一次循环中pre为initialValue,cur为数组的第一个元素
const array1 = [1, 2, 3, 4];
const res = array1.reduce((pre,cur,curIndex,arr)=>{
console.log("pre:", pre,",cur:", cur,",curIndex:", curIndex,",arr:", arr);
// pre: 1 ,cur: 2 ,curIndex: 1 ,arr: [ 1, 2, 3, 4 ]
// pre: 3 ,cur: 3 ,curIndex: 2 ,arr: [ 1, 2, 3, 4 ]
// pre: 6 ,cur: 4 ,curIndex: 3 ,arr: [ 1, 2, 3, 4 ]
return cur+pre;
})
console.log(res); // 10
- 如果没有initialValue,则第一次循环中pre为数组的第一个元素,cur为第二个元素
const array1 = [1, 2, 3, 4];
const res = array1.reduce((pre,cur,curIndex,arr)=>{
console.log("pre:", pre,",cur:", cur,",curIndex:", curIndex,",arr:", arr);
// pre: 0 ,cur: 1 ,curIndex: 0 ,arr: [ 1, 2, 3, 4 ]
// pre: 1 ,cur: 2 ,curIndex: 1 ,arr: [ 1, 2, 3, 4 ]
// pre: 3 ,cur: 3 ,curIndex: 2 ,arr: [ 1, 2, 3, 4 ]
// pre: 6 ,cur: 4 ,curIndex: 3 ,arr: [ 1, 2, 3, 4 ]
return cur+pre;
},0)
console.log(res); // 10
可以看出,给了初始值以后,会多加一次循环,因为遍历是从index=0开始遍历的
转换方式
const map = new Map();
map.set("basketball", "篮球");
map.set("soccer", "足球");
map.set("baseball", "棒球");
map.set("tennis", "网球");
转换方式1
const obj = Array.from(map).reduce((pre, cur) => {
const [key, value] = cur;
pre[key] = value;
return Object.assign(pre,{[key]:value});
}, {});
console.log(obj); // { basketball: '篮球', soccer: '足球', baseball: '棒球', tennis: '网球' }
在每个迭代中创建一个新对象(使用
Object.assign)时,性能会受到影响,还有一点是 Map 的 key 可以是非字符串的键,转换成字面量的 object 则不可以。
转换方式2
这种方式可以解决方式1中遇到的性能问题。
const obj = Array.from(map).reduce((pre, cur) => {
const [key, value] = cur;
pre[key] = value;
return pre;
}, {});
console.log(obj); // { basketball: '篮球', soccer: '足球', baseball: '棒球', tennis: '网球' }
转换方式3
const obj = [...map.entries()].reduce((obj, [key, value]) => {
obj[key] = value;
return obj;
}, {});
console.log(obj);
转换方式4
const obj = Array.from(map.entries()).reduce(
(main, [key, value]) => ({ ...main, [key]: value }),
{}
);
这行代码乍一看完全没问题,因为使用了扩展运算符还有点优雅的感觉,并且也是一行代码解决了战斗,但是在后面的性能测试过程中,第四种方法当真是让人大跌眼镜。
性能测试
现在我把四种写法放到一起,并且我创建一个拥有 10000 个 key 的 Map 来做转换,测试一下四种写法的性能。
// 创建一个较大的 map
for (let i = 0; i < 10000; i++) {
map.set(`a${i}`, i);
}
// MapConvertToObj1: 16.381ms
// MapConvertToObj2: 5.661ms
// MapConvertToObj3: 4.903ms
// MapConvertToObj4: 20344.747ms
看到这 4 种方式的性能输出,是不是大跌眼镜呢?并且第一种方式,果然是因为 Object.assign() 的用法存在性能开销,总体比第二种和第三种慢一点。