Map转Object

172 阅读3分钟

回顾reduce方法

reduce() 方法对数组中的每个元素按序执行一个由您提供的reducer函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

reduce()函数接受两个参数:

  • reducer:回调函数
  • initialValue:

reducer回调函数可以接受四个参数:

  • pre:上一次调用reducer的返回值,如果指定了initialValue,则第一次循环中preinitialValue
  • cur:当前要遍历的数组元素
  • index:当前遍历元素的下标
  • array:当前遍历的数组
  1. 如果有initialValue,则第一次循环中preinitialValuecur为数组的第一个元素
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
  1. 如果没有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() 的用法存在性能开销,总体比第二种和第三种慢一点。

参考文章