自从用了 Array.reduce() ,整个世界都清净了
在所有后 ES6 时代的数组方法中,我觉得最难理解的就是Array.reduce()。
从表面上看,它似乎是一个简单无趣的方法,并没有太大作用。 但是在不起眼的外表之下,Array.reduce()实际上是对开发人员工具包的强大而灵活的补充。
今天,我们就来研究一下通过Array.reduce()可以完成的一些有意思的事情。
原理
大部分现代的数组方法都返回一个新的数组,而 Array.reduce() 更加灵活。它可以返回任意值,它的功能就是将一个数组的内容聚合成单个值。
这个值可以是数字、字符串,甚至可以是对象或新数组。这就是一直难住我的部分,我没想到它这么灵活!
用法
Array.reduce()接受两个参数:一个是对数组每个元素执行的回调方法,一个是初始值。
这个回调也接受两个参数:accumulator是当前聚合值,current是数组循环时的当前元素。无论你返回什么值,都将作为累加器提供给循环中的下一个元素。初始值将作为第一次循环的累加器。
var myNewArray = [].reduce(function (accumulator, current) {
return accumulator;
}, starting);
让我们来看几个实际例子。
1. 数组求和
假设你想把一组数字加在一起。使用Array.forEach()大概可以这么做:
var total = 0;
[1, 2, 3].forEach(function (num) {
total += num;
});
这是Array.reduce()用得最多的例子了。我发现* accumulator *这个单词让人困惑,所以在示例中我改为sum,因为这里就是求和的意思。
var total = [1, 2, 3].reduce(function (sum, current) {
return sum + current;
}, 0);
这里传入0作为初始值。
在回调里,将当前值加入到 sum,第一轮循环时它的值是初始值0,然后变成1(初始值0加上当前元素值1),然后变成3(累加值 1加上当前元素值 2 ),以此类推
2. 组合多个数组方法
假设有一个wizards 数组:
var wizards = [
{
name: 'Harry Potter',
house: 'Gryfindor'
},
{
name: 'Cedric Diggory',
house: 'Hufflepuff'
},
{
name: 'Tonks',
house: 'Hufflepuff'
},
{
name: 'Ronald Weasley',
house: 'Gryfindor'
},
{
name: 'Hermione Granger',
house: 'Gryfindor'
}
];
你想创建一个仅包含住在 Hufflepuff 的巫师名字的新数组。一个可行的方法是使用Array.filter() 方法获取 house 属性为Hufflepuff的 wizards 。然后用Array.map() 方法创建一个只包含过滤后对象的name 属性的新数组。
var hufflepuff = wizards.filter(function (wizard) {
return wizard.house === 'Hufflepuff';
}).map(function (wizard) {
return wizard.name;
});
使用Array.reduce() 方法,我们可以用一步得到同样的结果,提高了性能。传递一个空数组[]作为初始值。每次循环时判断wizard.house 是否为Hufflepuff。如果是,就加入到newArr 中(即accumulator),否则啥也不做。
无论判断条件是否成立,最后都返回 newArr 作为下一次循环的accumulator 。
var hufflepuff = wizards.reduce(function (newArr, wizard) {
if (wizard.house === 'Hufflepuff') {
newArr.push(wizard.name);
}
return newArr;
}, []);
3. 从数组生成 HTML 标签
那么,如果想创建一个由住在 Hufflepuff 的巫师组成的无序列表要怎么做呢?这次不是给Array.reduce()传一个空数组作为初始值了,而是一个名为 html的空字符串''。
如果wizard.house 等于 Hufflepuff,我们就将wizard.name 用列表项li包裹起来,再拼接到html 字符串里。然后返回html 作为下一次循环的accumulator 。
var hufflepuffList = wizards.reduce(function (html, wizard) {
if (wizard.house === 'Hufflepuff') {
html += '' + wizard.name + ' ';
}
return html;
}, '');
在Array.reduce()前后添加无序列表的开始和结束标记,就可以把它插入到 DOM 中了。
var hufflepuffList = '
- ' + wizards.reduce(function (html, wizard) {
if (wizard.house === 'Hufflepuff') {
html += '
- ' + wizard.name + ' '; } return html; }, '') + '
发表评论 (审核通过后显示评论):