前言
在所有后 ES6 时代的数组方法中,我觉得最难理解的就是Array.reduce()。
从表面上看,它似乎是一个简单无趣的方法,并没有太大作用。 但是在不起眼的外表之下,Array.reduce()实际上是对开发人员工具包的强大而灵活的补充。
今天,我们就来研究一下通过Array.reduce()可以完成的一些有意思的事情。
原理
大部分现代的数组方法都返回一个新的数组,而 Array.reduce() 更加灵活。它可以返回任意值,它的功能就是将一个数组的内容聚合成单个值。
这个值可以是数字、字符串,甚至可以是对象或新数组。这就是一直难住我的部分,我没想到它这么灵活!
用法
Array.reduce()接受两个参数:一个是对数组每个元素执行的回调方法,一个是初始值。
这个回调接收4个参数,前两个参数是:accumulator是当前聚合值,current是数组循环时的当前元素。无论你返回什么值,都将作为累加器提供给循环中的下一个元素。初始值将作为第一次循环的累加器。
1. 数组求和
假设你想把一组数字加在一起。使用Array.forEach()大概可以这么做:
var total = [1, 2, 3].reduce(function (sum, current) {
return sum + current;
}, 0);
2. 组合多个数组方法
你想创建一个仅包含住在 Hufflepuff 的巫师名字的新数组。一个可行的方法是使用Array.filter() 方法获取 house 属性为Hufflepuff的 wizards 。然后用Array.map() 方法创建一个只包含过滤后对象的name 属性的新数组。
使用Array.reduce() 方法,我们可以用一步得到同样的结果,提高了性能。传递一个空数组[]作为初始值。每次循环时判断wizard.house 是否为Hufflepuff。如果是,就加入到newArr 中(即accumulator),否则啥也不做。
3. 从数组生成 HTML 标签
在Array.reduce()前后添加无序列表的开始和结束标记,就可以把它插入到 DOM 中了。
var hufflepuffList = '<ul>' + wizards.reduce(function (html, wizard) {
if (wizard.house === 'Hufflepuff') {
html += '<li>' + wizard.name + '</li>';
}
return html;
}, '') + '</ul>';
4. 数组元素分组
lodash 有个 groupBy()方法,可以将数组元素按照某个标准分组。
5. 合并数据到单个数组
假设你想把两份数据合并到一个数组,也就是把 points 数值添加到每个巫师对象上。你会怎么做?
Array.reduce() 方法特别适合!
var wizardsWithPoints = wizards.reduce(function (arr, wizard) {
// 移除巫师名字中的空格,用来获取对应的 points
var key = wizard.name.replace(' ', '');
// 如果wizard有points,则加上它,否则设置为0
if (points[key]) {
wizard.points = points[key];
} else {
wizard.points = 0;
}
// 把wizard对象加入到新数组里
arr.push(wizard);
// 返回这个数组
return arr;
}, []);
6. 合并数据到单个对象
如果你想合并两个来源的数据到一个对象中,也就是巫师的名字作为属性名,house 和 points 作为属性值,要怎么做呢?同样, Array.reduce() 很合适。
var wizardsAsAnObject = wizards.reduce(function (obj, wizard) {
// 移除巫师名字中的空格,用来获取对应的 points
var key = wizard.name.replace(' ', '');
// 如果wizard有points,则加上它,否则设置为0
if (points[key]) {
wizard.points = points[key];
} else {
wizard.points = 0;
}
// 删除 name 属性
delete wizard.name;
// 把 wizard 数据添加到新对象中
obj[key] = wizard;
// 返回该对象
return obj;
}, {});
总结: Array.reduce()
Array.reduce() 方法从我曾经认为不堪大用的东西,变成我最喜欢的 JavaScript 方法。那么,你应该使用它吗?什么时候可以用?
Array.reduce() 方法有着良好的浏览器支持。所有的现代浏览器都支持,包括 IE9 及以上。移动端浏览器也在很早之前就支持了。如果你还需要支持更老的浏览器,你可以添加一个 polyfill 来支持到 IE6。
Array.reduce()最大的槽点可能就是对于从来没接触过的人来说有点费解。组合使用Array.filter() 和Array.map()执行起来更慢,并且包含多余的步骤,但是更容易阅读,从方法名可以明显看出它要做的事情。
尽管如此,有时候Array.reduce() 也可以让复杂的事情看起来更简单。 groupBy() 工具函数就是个很好的例子。
最后,它应该成为你的工具箱里的另一个工具,一个使用得当就威力无穷的工具。
|
|