We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

# Array.prototype.reduce()

## 概述

`reduce()` 方法接收一个函数作为累加器（accumulator），数组中的每个值（从左到右）开始缩减，最终为一个值。

## 语法

``arr.reduce([callback, initialValue])``

### 参数

`callback`
`执行数组中每个值的函数，包含四个参数:`
`previousValue`

`currentValue`

`currentIndex`

`array`

`initialValue`

## 描述

`reduce` 为数组中的每一个元素依次执行回调函数，不包括数组中被删除或从未被赋值的元素，接受四个参数：

• `previousValu 上一次值`
• `currentValue 当前值`
• `currentIndex 当前值的索引`
• `array 数组`

``````var maxCallback = ( pre, cur ) => Math.max( pre.x, cur.x );
var maxCallback2 = ( max, cur ) => Math.max( max, cur );

// reduce() 没有初始值 initialValue
[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42        结果1
[ { x: 22 }            ].reduce( maxCallback ); // { x: 22 } 结果2
[                      ].reduce( maxCallback ); // TypeError 结果3

// map/reduce; reduce有初始值0, 更好的方法, 对于空数组也能正常工作
[ { x: 22 }, { x: 42 } ].map( el => el.x )
.reduce( maxCallback2 , 0 );``````

### reduce是如何工作的

```[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, index, array){
return previousValue + currentValue;
});```

`previousValue` `currentValue` `index` `array` return value
first call `0` `1` `1` `[0,1,2,3,4]` `1`
second call `1` `2` `2` `[0,1,2,3,4]` `3`
third call `3` `3` `3` `[0,1,2,3,4]` `6`
fourth call `6` `4` `4` `[0,1,2,3,4]` `10`

`reduce` 的返回值是回调函数最后一次被调用的返回值（10）。

``[0, 1, 2, 3, 4].reduce( (prev, curr) => prev + curr );``

``````[0,1,2,3,4].reduce( (previousValue, currentValue, currentIndex, array) => {
return previousValue + currentValue;
}, 10);``````
`previousValue` `currentValue` `index` `array` return value
first call `10` `0` `0` `[0,1,2,3,4]` `10`
second call `10` `1` `1` `[0,1,2,3,4]` `11`
third call `11` `2` `2` `[0,1,2,3,4]` `13`
fourth call `13` `3` `3` `[0,1,2,3,4]` `16`
fifth call `16` `4` `4` `[0,1,2,3,4]` `20`

## 例题

### 将数组所有项相加

```var total = [0, 1, 2, 3].reduce(function(a, b) {
return a + b;
}, 0);
// total == 6```

``var total = [ 0, 1, 2, 3 ].reduce( ( acc, cur ) => acc + cur, 0 );``

### 扁平化一个二维数组

```var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
return a.concat(b);
}, []);
// flattened is [0, 1, 2, 3, 4, 5]
```

## 兼容旧环境（Polyfill）

`Array.prototype.reduce` 被添加到 ECMA-262 标准第 5 版；因此可能在某些实现环境中不被支持。可以将下面的代码插入到脚本开头来允许在那些未能原生支持 `reduce` 的实现环境中使用它。

``````// Production steps of ECMA-262, Edition 5, 15.4.4.21
// Reference: http://es5.github.io/#x15.4.4.21
if (!Array.prototype.reduce) {
Array.prototype.reduce = function(callback /*, initialValue*/) {
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
var t = Object(this), len = t.length >>> 0, k = 0, value;
if (arguments.length == 2) {
value = arguments[1];
} else {
while (k < len && !(k in t)) {
k++;
}
if (k >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = t[k++];
}
for (; k < len; k++) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
return value;
};
}``````

## 规范

Specification Status Comment
ECMAScript 5.1 (ECMA-262)
Array.prototype.reduce
Standard Initial definition.
Implemented in JavaScript 1.8

ECMAScript 2015 (6th Edition, ECMA-262)
Array.prototype.reduce

Standard

## 浏览器兼容性

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support (Yes) 3.0 (1.9) 9 10.5 4.0
Feature Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support (Yes) (Yes) (Yes) (Yes) (Yes) (Yes)