代码
groupByWith(array, key) {
return array.reduce(function (accumulator, currentValue) {
(accumulator[currentValue[key]] = accumulator[currentValue[key]] || []).push(currentValue);
return accumulator;
}, {});
}
分析
先阅读此文了解 reduce 函数的概念和常规用法。
reduce
看完上面的文章,就会知道按属性对 object 数组进行分类,不过是文章中举例出来的最常规的用法之一而已。
然后我们再看,他的代码和 MDN 中的示例代码有啥区别,其实逻辑上没有任何区别,只是他的代码更加精简,看起来很紧凑、很酷而已。
我相信, reduce 没啥好说的了,他这里给 reduce 提供了一个初始值 {},通过了解 callback 首次执行的逻辑,我们知道提供了初始值的逻辑为:
- accumulator = initialValue(提供的初始值)
- currentValue = array[0] (源数组中索引为 0 的项)
即因为提供了初始值,所以 reduce 从索引为 0 的地方开始执行 callback 方法
最后一眼望去,最看不懂的地方其实就是第 3 行代码,因为写的过于紧凑,导致看起来很懵逼,但其实也就那么回事,我们拆分一下这句代码,并配合一段 JSON 数据来做解释:
[
{
name: '张三',
department: '部门A'
},
{
name: '李四',
department: '部门A'
},
{
name: '张三',
department: '部门B'
},
]
- (accumulator[currentValue[key]] = accumulator[currentValue[key]] || [])
- currentValue[key]: 首次 currenValue 就是 { name: ‘张三’, department: ‘部门A’ },key 假设外面传递进来的是 name,那 这句代码最后就得出 张三 这个字符串
- accumulator[currentValue[key]]:首次循环,我们知道 accumulator = initialValue,所以这里其实就是往累计器中增加了一个属性,key 为张三,所以这一步仅仅是动态计算属性名然后添加到对象中
- = accumulator[currentValue[key]] || []:这句话分为左右两部分,因为使用了 || ,那么我们就知道如果 || 左边的表达式计算出来的结果没有值,就会用右边的值,如果左边有值,就不会用右边的值。
那我们就可以带入来思考一下 accumulator[currentValue[key]] 的结果是什么,就是取 accumulator 对象中某个属性的值啊,即 accumulator[‘张三’],所以这里取的是 key 为张三的 value,所以如果 accumulator 中已经有张三,就要拿到张三的的值(数组),如果没有张三,就声明一个空数组,这样做的意义是什么呢?因为后续我们需要往这个数组里面 push 东西啊。
简单解释一下就是:如果有张三,就先得到张三的值(值为数组),然后往已有的这个值(数组)里面 push 东西,如果没有就声明一个空数组。
- .push(currentValue);
将上一步得到的数组作为基础,然后调用 .push(currentValue) 往其中新增项