Array.prototype.forEach()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
forEach()
メソッドは、与えられた関数を、配列の各要素に対して一度ずつ実行します。
試してみましょう
構文
forEach(callbackFn)
forEach(callbackFn, thisArg)
引数
返値
なし (undefined
)。
解説
forEach()
メソッドは反復処理メソッドです。指定された関数 callbackFn
を配列に含まれる各要素に対して一度ずつ、昇順で呼び出します。 map()
と異なり、 forEach()
は常に undefined
を返し、連鎖させることはできません。典型的な使用する用途は、チェーンの終わりで副次効果を実行することです。これらのメソッドが一般的にどのように動作するのかについての詳細は、反復処理メソッドの節をご覧下さい。
callbackFn
は値が割り当てられている配列インデックスに対してのみ呼び出されます。疎配列で空のスロットに対しては呼び出されません。
forEach()
メソッドは汎用的です。これは this
値に length
プロパティと整数キーのプロパティがあることだけを期待します。
例外を発生する以外の方法で、 forEach()
ループを止めたり脱出したりする方法はありません。そのような動作を行う場合、 forEach()
メソッドは適切な方法ではありません。
早期終了は for
, for...of
, for...in
のようなループ文で行うことができます。また、every()
, some()
, find()
, findIndex()
のような配列メソッドも、それ以上の反復処理が不要な場合は、直ちに反復処理を停止します。
forEach()
は同期関数を期待します。プロミスを待ちません。forEach
のコールバックとしてプロミス(または非同期関数)を使用する場合は、その意味合いを理解しておくようにしてください。
const ratings = [5, 4, 5];
let sum = 0;
const sumFunction = async (a, b) => a + b;
ratings.forEach(async (rating) => {
sum = await sumFunction(sum, rating);
});
console.log(sum);
// 本来期待される出力: 14
// 実際の出力: 0
一連の非同期処理を順次または並列に実行するには、プロミスの合成を参照してください。
例
for ループから forEach への変換
const items = ["item1", "item2", "item3"];
const copyItems = [];
// before
for (let i = 0; i < items.length; i++) {
copyItems.push(items[i]);
}
// after
items.forEach((item) => {
copyItems.push(item);
});
配列の内容の出力
メモ: 配列の内容をコンソールに表示するために、配列の整形済みのバージョンを表示する console.table()
を使用することができます。
以下の例では同じことを forEach()
を使用して行う他の方法を説明しています。
次のコードは配列の要素ごとに、コンソールに 1 行ずつ要素の内容を出力します。
const logArrayElements = (element, index /*, array */) => {
console.log(`a[${index}] = ${element}`);
};
// 配列の 2 の位置には項目が存在しないため、
// スキップされることに注意してください
[2, 5, , 9].forEach(logArrayElements);
// 出力結果:
// a[0] = 2
// a[1] = 5
// a[3] = 9
thisArg の使用
以下の(不自然な)例は、配列の中の各項目からオブジェクトのプロパティを更新します。
class Counter {
constructor() {
this.sum = 0;
this.count = 0;
}
add(array) {
// Only function expressions have their own this bindings.
array.forEach(function countEntry(entry) {
this.sum += entry;
++this.count;
}, this);
}
}
const obj = new Counter();
obj.add([2, 5, 9]);
console.log(obj.count); // 3
console.log(obj.sum); // 16
thisArg
引数 (this
) が forEach()
に提供されているため、callbackFn
の呼び出しのたびにこれが渡されます。コールバックはこれを this
の値として使用します。
オブジェクトをコピーする関数
次のコードは与えられたオブジェクトのコピーを生成します。
オブジェクトのコピーを作成するには様々な方法があります。
以下のものは一つの方法で、Array.prototype.forEach()
が Object.*
ユーティリティ関数を使用して、どのように動作するかを説明しています。
const copy = (obj) => {
const copy = Object.create(Object.getPrototypeOf(obj));
const propNames = Object.getOwnPropertyNames(obj);
propNames.forEach((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
配列の平坦化
次の例は学習目的だけのものです。組み込みメソッドを使用して配列を平坦化したい場合は、Array.prototype.flat()
を使用することができます。
const flatten = (arr) => {
const result = [];
arr.forEach((item) => {
if (Array.isArray(item)) {
result.push(...flatten(item));
} else {
result.push(item);
}
});
return result;
};
// 使用方法
const nested = [1, 2, 3, [4, 5, [6, 7], 8, 9]];
console.log(flatten(nested)); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
callbackFn の第 3 引数の使用
array
引数は、配列の別の要素にアクセスしたい場合、特に配列を参照する既存の変数を保有していない場合に便利です。次の例では、最初の filter()
を使用して正の値を抽出し、次に forEach()
を使用してその付近をログに記録します。
const numbers = [3, -1, 1, 4, 1, 5];
numbers
.filter((num) => num > 0)
.forEach((num, idx, arr) => {
// arr 引数がない場合、変数に保存せずに中間配列に
// 簡単にアクセスする方法はない
console.log(arr[idx - 1], num, arr[idx + 1]);
});
// undefined 3 1
// 3 1 4
// 1 4 1
// 4 1 5
// 1 5 undefined
疎配列に対する forEach() の使用
const arraySparse = [1, 3, /* 空 */, 7];
let numCallbackRuns = 0;
arraySparse.forEach((element) => {
console.log({ element });
numCallbackRuns++;
});
console.log({ numCallbackRuns });
// { element: 1 }
// { element: 3 }
// { element: 7 }
// { numCallbackRuns: 3 }
3 と 7 の間の値がないところで、コールバック関数が呼び出されなかったことが分かります。
配列以外のオブジェクトに対する forEach() の呼び出し
forEach()
メソッドは this
の length
プロパティを読み込み、次にキーが length
より小さい非負の整数である各プロパティにアクセスします。
const arrayLike = {
length: 3,
0: 2,
1: 3,
2: 4,
3: 5, // length が 3 であるため forEach() からは無視される
};
Array.prototype.forEach.call(arrayLike, (x) => console.log(x));
// 2
// 3
// 4
仕様書
Specification |
---|
ECMAScript Language Specification # sec-array.prototype.foreach |
ブラウザーの互換性
BCD tables only load in the browser