Array.prototype.forEach()

forEach() メソッドは与えられた関数を、配列の各要素に対して一度ずつ実行します。

構文

arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);

引数

callback
各要素に対して実行するコールバック関数で、3つの引数をとります。
currentValue
現在処理されている配列の要素です。
index Optional
現在処理されている配列の要素のインデックスです。
array Optional
forEach() が呼び出されている配列です。
thisArg Optional
callback 内で this として使用する値です。

返値

undefined です。

解説

forEach() は、与えられた関数 callback を配列に含まれる各要素に対して一度ずつ、昇順で呼び出します。インデックスプロパティが削除されていたり、初期化されていなかったりした場合 (すなわち疎らな配列、以下の例を参照) は呼び出されません。

callback は次の 3 つの引数で呼び出されます。

  1. 要素の値
  2. 要素のインデックス
  3. 走査されている配列

forEach()thisArg 引数が与えられると、 callback の呼び出し時にそのオブジェクトが this として使用されます。 callback によって究極に管理される this の値は、関数から見える this を特定する一般規則に従います。

forEach() によって処理される配列要素の範囲は、 callback が最初に呼び出される前に設定されます。 forEach() の呼び出しが開始された後に追加された配列要素に対しては、 callback は実行されません。既存の配列要素が変更または削除された場合、 callback に渡される値は forEach() がそれらを参照した時点での値になります。削除された配列要素を参照することはありません。既に参照された配列要素がイテレーションの間 (e.g. shift()を使用して) に削除された場合、後の要素は飛ばされます。 - 以下の例を参照してください

forEach() は配列の各要素に対して callback 関数を一度ずつ実行します。 map()reduce() と異なり、返値は常に undefined であり、チェーンできません。チェーンの最後に副作用を生じさせるのが典型的な使用法です。

forEach() は呼び出された配列を変化させません (ただし callback が、呼び出された場合に変化させる可能性があります)。

例外を発生さえるする以外の方法で、 forEach() ループを止めることはできません。ループ中に中断する必要がある場合、 forEach() メソッドは適切な方法ではありません。

早期終了を行うには下記のような手段が適しています。

他の Array のメソッドである every(), some(), find(), findIndex() は、配列の要素を検査する際、 truthy の値を返すことで以降の繰り返しが必要であるかどうかを決めます。

初期化されていない値については何もしない (疎らな配列)

const arraySparse = [1,3,,7];
let numCallbackRuns = 0;

arraySparse.forEach(function(element){
  console.log(element);
  numCallbackRuns++;
});

console.log("numCallbackRuns: ", numCallbackRuns);

// 1
// 3
// 7
// numCallbackRuns: 3
// 備考: 見ての通り、存在しない 3 から 7 までの値では、コールバック関数が呼び出されません。

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() を使用して行う他の方法を説明します。

次のコードは配列の要素ごとに、コンソールに 1 行ずつ要素の内容を出力します。

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

// Notice that index 2 is skipped since there is no item at
// that position in the array.
[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);
  // ^---- Note
};

const obj = new Counter();
obj.add([2, 5, 9]);
obj.count;
// 3 
obj.sum;
// 16

thisArg 引数 (this) が forEach() に提供され、 callback の呼び出しのたびに、 this の値として使用するために渡されます。

アロー関数式を使用して関数の引数を渡す場合、 thisArg 引数は、アロー関数が文法的に this の値に結び付けられているため省略可能です。

オブジェクトをコピーする関数

次のコードは与えられたオブジェクトのコピーを生成します。オブジェクトのコピーを生成するには他にもいくつか方法があります。次のものは一つの方法であり、 Array.prototype.forEach() が ECMAScript 5 の Object.* メタプロパティ関数を使用することでどのように動作するかを説明するために示しているものです。

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

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

  return copy;
}

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

配列が繰り返しの間に変更され、他の要素が飛ばされる場合

次の例では "one", "two", "four" をログ出力します。値 "two" を持つ項目に達した時、配列全体の最初の項目はシフトして外れ、すべての残りの項目が1つ上の位置に繰り上がります。 "four" が配列の以前の位置に来るため、 "three" が飛ばされます。 forEach() は繰り返しの前に配列のコピーを作成しません。

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

配列の平板化

次の例は学習目的だけのものです。内蔵メソッドを使用して配列を平板化したい場合は、 Array.prototype.flat() を使用することができます (ES2019 の一部となる予定で、一部のブラウザーではすでに実装済み)。

/**
 * Flattens passed array in one dimensional array
 *
 * @params {array} arr
 * @returns {array}
 */
function flatten(arr) {
  const result = []

  arr.forEach((i) => {
    if (Array.isArray(i)) {
      result.push(...flatten(i))
    } else {
      result.push(i)
    }
  })
  
  return result
}

// Usage
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]]

flatten(problem) // [1, 2, 3, 4, 5, 6, 7, 8, 9]

仕様書

仕様書 状態 備考
ECMAScript Latest Draft (ECMA-262)
Array.prototype.forEach の定義
ドラフト
ECMAScript 2015 (6th Edition, ECMA-262)
Array.prototype.forEach の定義
標準
ECMAScript 5.1 (ECMA-262)
Array.prototype.forEach の定義
標準 初回定義。 JavaScript 1.6 で実装。

ブラウザーの互換性

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
forEachChrome 完全対応 ありEdge 完全対応 12Firefox 完全対応 1.5IE 完全対応 9Opera 完全対応 ありSafari 完全対応 ありWebView Android 完全対応 ありChrome Android 完全対応 ありFirefox Android 完全対応 4Opera Android 完全対応 ありSafari iOS 完全対応 ありSamsung Internet Android 完全対応 ありnodejs 完全対応 あり

凡例

完全対応  
完全対応

関連情報