自从学会了 Array.reduce() ，再也离不开它

·  阅读 25335

用法

`Array.reduce()`接受两个参数：一个是对数组每个元素执行的回调方法，一个是初始值。

``````
var myNewArray = [].reduce(function (accumulator, current) {
return accumulator;
}, starting);

1. 数组求和

``````
var total = 0;

[1, 2, 3].forEach(function (num) {
total += num;
});

``````
var total = [1, 2, 3].reduce(function (sum, current) {
return sum + current;
}, 0);

2. 组合多个数组方法

``````
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'
}
];

``````
var hufflepuff = wizards.filter(function (wizard) {
return wizard.house === 'Hufflepuff';
}).map(function (wizard) {
return wizard.name;
});

``````
var hufflepuff = wizards.reduce(function (newArr, wizard) {
if (wizard.house === 'Hufflepuff') {
newArr.push(wizard.name);
}
return newArr;
}, []);

3. 从数组生成 HTML 标签

``````
var hufflepuffList = wizards.reduce(function (html, wizard) {
if (wizard.house === 'Hufflepuff') {
html += '<li>' + wizard.name + '</li>';
}
return 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()`方法，可以将数组元素按照某个标准分组。

``````
var numbers = [6.1, 4.2, 6.3];

// 返回 {'4': [4.2], '6': [6.1, 6.3]}
_.groupBy(numbers, Math.floor);

``````
var words = ['one', 'two', 'three'];

// 返回 {'3': ['one', 'two'], '5': ['three']}
_.groupBy(words, 'length');

用 `Array.reduce()` 实现 `groupBy()`函数

``````
var groupBy = function (arr, criteria) {
return arr.reduce(function (obj, item) {
// 省略代码
}, {});
};

``````
var groupBy = function (arr, criteria) {
return arr.reduce(function (obj, item) {

// 判断criteria是函数还是属性名
var key = typeof criteria === 'function' ? criteria(item) : item[criteria];

// 如果属性不存在，则创建一个
if (!obj.hasOwnProperty(key)) {
obj[key] = [];
}

// 将元素加入数组
obj[key].push(item);

// 返回这个对象
return obj;

}, {});
};

5. 合并数据到单个数组

``````
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'
}
];

``````
var points = {
HarryPotter: 500,
CedricDiggory: 750,
RonaldWeasley: 100,
HermioneGranger: 1270
};

`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. 合并数据到单个对象

``````
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()`执行起来更慢，并且包含多余的步骤，但是更容易阅读，从方法名可以明显看出它要做的事情。