`forEach()` 方法对数组的每个元素执行一次提供的函数。

The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

## 语法

    arr.forEach(callback[, thisArg]);

### 参数

`callback`
  为数组中每个元素执行的函数，该函数接收三个参数：
  `currentValue`
    数组中正在处理的当前元素。
  `index` 可选
    数组中正在处理的当前元素的索引。
  `array` 可选
    `forEach()` 方法正在操作的数组。
`thisArg` 可选
  可选参数。当执行回调函数时用作 `this` 的值(参考对象)。

### 返回值

`undefined`.

## 描述

`forEach` 方法按升序为数组中含有效值的每一项执行一次`callback` 函数，那些已删除或者未初始化的项将被跳过（例如在稀疏数组上）。

`callback` 函数会被依次传入三个参数：

- 数组当前项的值
- 数组当前项的索引
- 数组对象本身

如果给 `forEach()` 传递了 `thisArg` 参数，当调用时，它将被传给 `callback` 函数，作为它的 `this` 值。否则，将会传入 `undefined` 作为它的 `this` 值。`callback` 函数最终可观察到 `this` 值，这取决于函数观察到 `this` 的常用规则。

`forEach` 遍历的范围在第一次调用 `callback` 前就会确定。调用 `forEach` 后添加到数组中的项不会被 `callback` 访问到。如果已经存在的值被改变，则传递给 `callback` 的值是 `forEach` 遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了（例如使用 `shift()`），之后的元素将被跳过 - 参见下面的示例。

`forEach()` 为每个数组元素执行callback函数；不像 `map()` 或者 `reduce()`，它总是返回 `undefined` 值，并且不可链式调用。典型用例是在一个链的最后执行副作用。

`forEach()` does not mutate the array on which it is called (although `callback`, if invoked, may do so).

注意： 没有办法中止或者跳出 `forEach()` 循环，除了抛出一个异常。如果你需要这样，使用 `forEach()` 方法是错误的。

若你需要提前终止循环，你可以使用：

- 简单循环
- for...of 循环
- `Array.prototype.every()`
- `Array.prototype.some()`
- `Array.prototype.find()`
- `Array.prototype.findIndex()`

这些数组方法可以对数组元素判断，以便确定是否需要继续遍历：`every()`，`some()`，`find()`，`findIndex()`

译者注：若条件允许，也可以使用 `filter()` 提前过滤出需要遍历的部分，再用 `forEach()` 处理。

## 示例

### for 循环转换为 forEach

    const items = ['item1', 'item2', 'item3'];
    const copy = [];

    // before
    for (let i=0; i<items.length; i++) {
      copy.push(items[i]);
    }

    // after
    items.forEach(function(item){
      copy.push(item);
    });

### 打印出数组的内容

注意：为了在控制台中显示数组的内容，你可以使用 `console.table()` 来展示经过格式化的数组。下面的例子则是另一种使用 `forEach()` 的格式化的方法。

下面的代码会为每一个数组元素输出一行记录：

    function logArrayElements(element, index, array) {
      console.log('a[' + index + '] = ' + element);
    }

    // 注意索引 2 被跳过了，因为在数组的这个位置没有项
    [2, 5, , 9].forEach(logArrayElements);
    // logs:
    // a[0] = 2
    // a[1] = 5
    // a[3] = 9

### 使用 `thisArg`

举个勉强的例子，从每个数组中的元素值中更新一个对象的属性：

    function Counter() {
        this.sum = 0;
        this.count = 0;
    }

    Counter.prototype.add = function(array) {
        array.forEach(function(entry) {
            this.sum += entry;
            ++this.count;
        }, this);
        //console.log(this);
    };

    var obj = new Counter();
    obj.add([1, 3, 5, 7]);

    obj.count;
    // 4 === (1+1+1+1)
    obj.sum;
    // 16 === (1+3+5+7)

因为 `thisArg` 参数（`this`）传给了 `forEach()`，每次调用时，它都被传给 `callback` 函数，作为它的 `this` 值。

注意：如果使用箭头函数表达式来传入函数参数，`thisArg` 参数会被忽略，因为箭头函数在词法上绑定了 `this` 值。

### 对象复制函数

下面的代码会创建一个给定对象的副本。 创建对象的副本有不同的方法，以下是只是一种方法，并解释了 `Array.prototype.forEach()` 是如何使用 ECMAScript 5 `Object.*` 元属性（meta property ）函数工作的。

    function copy(obj) {
      var copy = Object.create(Object.getPrototypeOf(obj));
      var propNames = Object.getOwnPropertyNames(obj);

      propNames.forEach(function(name) {
        var desc = Object.getOwnPropertyDescriptor(obj, name);
        Object.defineProperty(copy, name, desc);
      });

      return copy;
    }

    var obj1 = { a: 1, b: 2 };
    var obj2 = copy(obj1); // obj2 looks like obj1 now

### 如果数组在迭代时被修改了，则其他元素会被跳过。

下面的例子会输出"one", "two", "four"。当到达包含值"two"的项时，整个数组的第一个项被移除了，这导致所有剩下的项上移一个位置。因为元素 "four"现在在数组更前的位置，"three"会被跳过。 `forEach()`不会在迭代之前创建数组的副本。

    var words = ['one', 'two', 'three', 'four'];
    words.forEach(function(word) {
      console.log(word);
      if (word === 'two') {
        words.shift();
      }
    });
    // one
    // two
    // four

## Polyfill

`forEach` 是在第五版本里被添加到 ECMA-262 标准的；这样它可能在标准的其他实现中不存在，你可以在你调用 `forEach` 之前 插入下面的代码，在本地不支持的情况下使用 `forEach()`。该算法是 ECMA-262 第5版中指定的算法。算法假定 `Object` 和 `TypeError` 拥有它们的初始值。`callback.call` 等价于 `Function.prototype.call()`。

    // Production steps of ECMA-262, Edition 5, 15.4.4.18
    // Reference: http://es5.github.io/#x15.4.4.18
    if (!Array.prototype.forEach) {

      Array.prototype.forEach = function(callback, thisArg) {

        var T, k;

        if (this == null) {
          throw new TypeError(' this is null or not defined');
        }

        // 1. Let O be the result of calling toObject() passing the
        // |this| value as the argument.
        var O = Object(this);

        // 2. Let lenValue be the result of calling the Get() internal
        // method of O with the argument "length".
        // 3. Let len be toUint32(lenValue).
        var len = O.length >>> 0;

        // 4. If isCallable(callback) is false, throw a TypeError exception.
        // See: http://es5.github.com/#x9.11
        if (typeof callback !== "function") {
          throw new TypeError(callback + ' is not a function');
        }

        // 5. If thisArg was supplied, let T be thisArg; else let
        // T be undefined.
        if (arguments.length > 1) {
          T = thisArg;
        }

        // 6. Let k be 0
        k = 0;

        // 7. Repeat, while k < len
        while (k < len) {

          var kValue;

          // a. Let Pk be ToString(k).
          //    This is implicit for LHS operands of the in operator
          // b. Let kPresent be the result of calling the HasProperty
          //    internal method of O with argument Pk.
          //    This step can be combined with c
          // c. If kPresent is true, then
          if (k in O) {

            // i. Let kValue be the result of calling the Get internal
            // method of O with argument Pk.
            kValue = O[k];

            // ii. Call the Call internal method of callback with T as
            // the this value and argument list containing kValue, k, and O.
            callback.call(T, kValue, k, O);
          }
          // d. Increase k by 1.
          k++;
        }
        // 8. return undefined
      };
    }

## 规范

规范 | 状态 | 备注
--- | --- | ---
ECMAScript 5.1 (ECMA-262) Array.prototype.forEach | Standard | Initial definition. Implemented in JavaScript 1.6.
ECMAScript 2015 (6th Edition, ECMA-262) Array.prototype.forEach | Standard |
ECMAScript Latest Draft (ECMA-262) Array.prototype.forEach | Draft |

## 浏览器兼容性

The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

Update compatibility data on GitHub

| Desktop | Mobile | Server
| Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | Safari on iOS | Samsung Internet | Node.js
`forEach` | Chrome Full support Yes | Edge Full support 12 | Firefox Full support 1.5 | IE Full support 9 | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile Full support Yes | Firefox Android Full support 4 | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes | nodejs Full support Yes

### Legend

Full support
  Full support

## 参见

- `Array.prototype.find()`
- `Array.prototype.findIndex()`
- `Array.prototype.map()`
- `Array.prototype.filter()`
- `Array.prototype.every()`
- `Array.prototype.some()`
- `Map.prototype.forEach()`
- `Set.prototype.forEach()`