源码
点击这里前往Github查看本文源码。
背景
先把封面图中的需求摘抄下来:
代码语言:javascript复制['Red', 'White', 'Yellow']
// 转为
{ Red: 'Red', White: 'White', Yellow: 'Yellow' }
接下我来用几个方法去实现这个功能。
传统方法
自然是没有for循环解决不了的问题:
代码语言:javascript复制const Colors = ['Red', 'White', 'Yellow']
const ObjColors = {}
for (const color of Colors) {
ObjColors[color] = color
}
console.log(ObjColors)
// { Red: 'Red', White: 'White', Yellow: 'Yellow' }
这个方法固然没错,但是for循环已经有被滥用的趋势了,如果说在可以使用函数式API的情况下,我们最好尝试着使用它们。
map与reduce
当我不理解reduce
函数的功能时,我先想到了这个方法:
- 先把每一项转化成
{ item: 'item' }
的对象, - 然后通过展开运算符合并它们。
const Colors = ['Red', 'White', 'Yellow']
.map(item => ({ [item]: item }))
.reduce((pre, cur) => ({ ...pre, ...cur }))
console.log(Colors)
// { Red: 'Red', White: 'White', Yellow: 'Yellow' }
比一开始的代码更加清晰了,但是感觉map
这一步是否有点多余? 接下来的纯reduce
就可以解决这个问题。
reduce
相信很多人和我一样,在印象中reduce
函数就是个用来求和的,比如:
const arr = [1, 2, 3]
console.log(arr.reduce((a, b) => a b))
// 6
但它能做的不只这些,我们可以给它传第二个参数initialValue
,看一下运行过程:
const arr = [1, 2, 3]
console.log('No initial value')
let result = arr.reduce((pre, cur) => {
console.log(pre, cur)
return pre cur
})
console.log('Result is', result)
console.log('nWith initial value')
result = arr.reduce((pre, cur) => {
console.log(pre, cur)
return pre cur
}, 0)
console.log('Result is', result)
运行结果是:
代码语言:javascript复制No initial value
1 2
3 3
Result is 6
With initial value
0 1
1 2
3 3
Result is 6
通过观察可以知道,如果说不传入初始值,第一次调用是callback(arr[0], arr[1])
。
而传入初始值,第一次调用就是callback(initialValue, arr[0])
。
通过这个特性,我们可以通过纯粹的reduce
方法实现我们一开始的需求:
const Colors = ['Red', 'White', 'Yellow']
.reduce((pre, cur) => ({ ...pre, [cur]: cur }), {})
console.log(Colors)
// { Red: 'Red', White: 'White', Yellow: 'Yellow' }
这是前面有一篇文章里面的需求,就是要把这些字符串存起来当成枚举使用。