ECMAScript 5 で追加されたものを一覧化しました。
forEach()
for 文の場合:
// 要素の合計を求める const array = [1, 2, 3, 4, 5]; let sum = 0; for (let index = 0; index < array.length; index += 1) { sum += array[index]; } console.log(sum);
forEach() で記述すると:
const array = [1, 2, 3, 4, 5]; let sum = 0; array.forEach((element) => { sum += element; }); console.log(sum);
Pros
- 配列の要素だけに注目できる
- for 分だとインデックスを正確に操作する必要があるが、forEach() なら確実に配列を巡回できる
- 要素を与えられるので、配列にアクセスすることがなく、配列そのもの意図せずに壊すことがない
- インデックスも使える(関数の引数は、配列要素の値、配列要素のインデックス、配列自身の 3 つが渡される)
Cons
- for 文と違って途中で break できない
単純に配列を巡回させたいなら forEach() の方が良い。
map()
for 文の場合:
// それぞれの要素を2倍した配列を求める const array = [1, 2, 3, 4, 5]; const array2x = []; for (let index = 0; index < array.length; index += 1) { array2x[index] = array[index] * 2; } console.log(array2x);
map() で記述すると:
const array = [1, 2, 3, 4, 5]; const array2x = array.map(value => value * 2); console.log(array2x);
Pros
- 新しい配列を作成する処理ではなく、配列の要素を作成する処理に注目できる
- インデックスも使える(関数の引数は forEach() と同じ)
Cons
- 特になし
繰り返しの目的が、配列を元に新しい配列を作ることなら、map() の方が良い。
filter()
for 文の場合:
// インデックスが奇数の要素を求める const array = ['a', 'b', 'c', 'd', 'e']; const oddArray = []; for (let index = 0; index < array.length; index += 1) { if (index % 2 !== 0) { oddArray.push(array[index]); } } console.log(oddArray);
filter() で記述すると:
const array = ['a', 'b', 'c', 'd', 'e']; const oddArray = array.filter((value, index) => index % 2 !== 0); console.log(oddArray);
Pros
- 新しい配列を作成する処理ではなく、取得条件に注目できる
- インデックスも使える(関数の引数は forEach() と同じ)
Cons
- 特になし
繰り返しの目的が、配列から特定条件の要素を取得することなら、filter() の方が良い。
every(), some()
for 文の場合:
// 配列の要素が全て奇数か判定する const array = [1, 2, 3, 4, 5]; let isAllOddNumber = true; for (let index = 0; index < array.length; index += 1) { if (array[index] % 2 === 0) { isAllOddNumber = false; } } console.log(isAllOddNumber); // 配列の要素に奇数が含まれているか判定する let isSomeOddNumber = false; for (let index = 0; index < array.length; index += 1) { if (array[index] % 2 !== 0) { isSomeOddNumber = true; } } console.log(isSomeOddNumber);
every(), some() で記述すると:
const array = [1, 2, 3, 4, 5]; const isAllOddNumber = array.every(value => value % 2 !== 0); console.log(isAllOddNumber); const isSomeOddNumber = array.some(value => value % 2 !== 0); console.log(isSomeOddNumber);
Pros
- 配列の操作ではなく、 判定条件に注目できる
- インデックスも使える(関数の引数は forEach() と同じ)
Cons
- 特になし
配列が空の場合は、every() は常に true、some は常に false を返す。 繰り返しの目的が、配列から特定条件の要素の存在を判定することなら、every(), some() の方が良い。
reduce(), reduceRight()
for 文の場合:
// 配列の要素から最大値を求める const array = [1, 2, 3, 4, 5]; let max = 0; for (let index = 0; index < array.length; index += 1) { if (array[index] > max) { max = array[index]; } } console.log(max);
reduce() で記述すると:
const array = [1, 2, 3, 4, 5]; const max = array.reduce((result, value) => (value > result ? value : result), 0); console.log(max);
reduce(), reduceRight() はちょっと難しい。 reduce には色々な意味があるが、「~を単純化する」「~をまとめる」という意味で理解すると機能を想像しやすいかもしれない。
例で言うところの result は各要素の繰り返し処理に引き継がれる値で、value は各要素の値になる。なお、省略しているが、3番目には配列の要素のインデックス、4番目には配列自身が引数として渡される。 reduce() の第2引数(例でいうと0)は、述語関数が一番最初に呼ばれるときの第1引数(例でいうと result)となる。reduceRight() は reduce() の逆順で処理するものである。
正直なところ微妙な感じ。forEach で十分なことが多そうなので、むしろむやみに多用しないほうが読みやすい印象がある。ほかのプログラマの事も考えて、慎重に採用したほうが良いだろう。
indexOf(), lastIndexOf()
for 文の場合:
// 配列から特定の値を持つ要素の一番最初のインデックスを求める const array = [0, 1, 2, 1, 0]; const search = 1; let result; for (let index = 0; index < array.length; index += 1) { if (array[index] === search) { result = index; break; } } console.log(result);
indexOf() で記述すると:
const array = [0, 1, 2, 1, 0]; const max = array.indexOf(1); console.log(max);
文字列操作でも同じ働きをするメソッドが用意されているので、説明不要かと思う。