【JavaScript】forEachで効率的に配列の要素を順に取り出す

JavaScriptのforEachとは?効率的に配列の要素を順に取り出す方法

森岡 駿

森岡 駿

開発エンジニア(Java、JavaScript)/エンジニア歴3年

JavaScriptで配列の1つ1つの要素をループ処理で順に取り出して処理を行なう時に用いられるメソッドの1つとして、forEachメソッドがあります。通常ループ処理を行なう時はfor文が用いられることが多いかと思いますが、forEachメソッドを使うことでfor文よりもシンプルなコードで処理を記述することができます。本記事では、forEachメソッドの基本的な使い方やどのような処理を行なうことができるかについて解説します。

One dayインターン

1.forEachメソッドの基本構文

JavaScriptのforEachメソッドは、以下のように記述します。

配列名.forEach(コールバック関数(配列の要素));

forEachメソッドは配列の要素を先頭から順に取り出し、引数に指定したコールバック関数を呼び出します。後述しますが、コールバック関数の引数として「配列の要素のインデックス」や「配列自身」を任意で追加して指定することも可能です。

1-1.forEachメソッドの使用例

forEachメソッドを使って配列の要素を順番に出力する例を以下に示します。

const fruits = [‘Apple’, ‘Banana’, ‘Cherry’];

fruits.forEach(function(fruit){
     console.log(fruit);
});

// ↓出力結果
// Apple
// Banana
// Cherry

コールバック関数の引数に指定したfruitに配列fruitsの要素であるApple’, ‘Banana’, ‘Cherry’が順番に入り、1つずつ出力されています。

1-2.for文との比較

1-1.の例をfor文で記述すると以下のようになります。

const fruits = [‘Apple’, ‘Banana’, ‘Cherry’];

for(var i = 0; i < fruits.length; i++){
     console.log(fruits[i]);
}

// ↓出力結果
// Apple
// Banana
// Cherry

for文では繰り返しのカウンター(i)やループの繰り返し条件(i < fruits.length)、カウンターの更新(i++)を指定する必要があります。カウンターのiを配列のインデックス番号として、配列fruitsの中身を順番に参照することで同じ結果となっています。

ただし、以下のように配列の途中の要素がない場合は異なる結果となります。

const fruits = [‘Apple’, ‘Banana’, , , ‘Cherry’];

// forEachメソッド
fruits.forEach(function(fruit){
     console.log(fruit);
});

// ↓出力結果
// Apple
// Banana
// Cherry

// for文
for(var i = 0; i < fruits.length; i++){
     console.log(fruits[i]);
}

// ↓出力結果
// Apple
// Banana
// undefined
// undefined
// Cherry

forEachメソッドでは要素がない場合処理がスキップされますが、for文ではスキップせずに処理されるため、要素が未定義であることを表すundefinedが出力されています。

1-3.引数のコールバック関数に複数の引数を指定する例

前述した通り、コールバック関数の引数として「配列の要素のインデックス」や「配列自身」を任意で指定することも可能です。

1-3-1.2つの引数を指定

コールバック関数に引数を2つ指定するときは、「配列の要素」と「配列の要素のインデックス」を指定します。以下に使用例を示します。

const numbers = [1, 2, 3];

numbers.forEach(function(number, index){
     console.log(“numbers[” + index + “] : “ + number);
});

// ↓出力結果
// numbers[0] : 1
// numbers[1] : 2
// numbers[2] : 3

コールバック関数の引数に指定したnumberに配列numbersの要素である1, 2, 3が、indexには配列numbersのインデックス番号である0, 1, 2が順番に入り、それぞれ出力されています。

1-3-2.3つの引数を指定

コールバック関数に引数を3つ指定するときは、「配列の要素」「配列の要素のインデックス」「配列自身」を指定します。以下に使用例を示します。

var numbers = [1, 2, 3];

numbers.forEach(function(number, index, array){
     array[index] = number * 2;
     console.log(array[index]);
});

// ↓出力結果
// 2
// 4
// 6

コールバック関数の引数に指定したarrayは配列numbers自身を表しており、処理の中でそれぞれの要素を2倍することで配列numbersを更新しています。


2.forEachメソッドの応用例

forEachメソッドの応用例をいくつか紹介します。

2-1.引数のコールバック関数をアロー関数で記述

引数のコールバック関数はアロー関数で記述することも可能です。例えば1-1.の例は以下のように書き換えることができます。

const fruits = [‘Apple’, ‘Banana’, ‘Cherry’];

fruits.forEach((fruit) => console.log(fruit));

// ↓出力結果
// Apple
// Banana
// Cherry

アロー関数を使用することでシンプルに記述することができます。1-3-2.のようにコールバック関数の処理が複数行ある場合は、以下のように処理の箇所を{}で囲います。

var numbers = [1, 2, 3];

numbers.forEach((number, index, array) => {
     array[index] = number * 2;
     console.log(array[index]);
});

// ↓出力結果
// 2
// 4
// 6

2-2.別で定義した関数を引数に指定

引数に直接コールバック関数の処理を記述せずとも、別で定義した関数を引数に指定して処理を行うことも可能です。

const fruits = [‘Apple’, ‘Banana’, ‘Cherry’];

function output(str) {
     console.log(str);
};

fruits.forEach(output);

// ↓出力結果
// Apple
// Banana
// Cherry

引数の値を出力する関数outputの関数名をforEachメソッドの引数に指定することで、別で定義した関数を呼び出して処理を行うことができます。

2-3.forEachメソッドの第2引数にオブジェクトを渡す例

forEachメソッドは第1引数のコールバック関数の他に、第2引数として任意のオブジェクトを指定することができます。第2引数として指定したオブジェクトは、コールバック関数内でthisにより呼び出して使用することができます。

const fruits = [‘Apple’, ‘Banana’, ‘Cherry’];

const fruitsPrice = {
     ‘Apple’: 100,
     ‘Banana’: 120,
     ‘Cherry’: 80,
     ‘Orange’: 90,
     ‘Lemon’: 110,
};

fruits.forEach(function(fruit){
     console.log(`${fruit}の値段は${this[fruit]円です。}`);
}, fruitsPrice);

// ↓出力結果
// Appleの値段は100円です。
// Bananaの値段は120円です。
// Cherryの値段は80円です。

コールバック関数内のthisはfruitsPriceを表しているため、配列fruitsの要素をキーとしてfruitsPriceの100や120といった値を取り出すことができます。


3.forEachメソッドの注意点

forEachメソッドは配列を処理する際に便利な一方で、いくつか注意点があります。

3-1.continueによる処理の中断やbreakによる抜け出しができない

forEachメソッドでは、continueで処理を中断させたり、breakで処理自体を抜け出したりすることができません。forEachメソッド内でcontinueやbreakを記述するとエラーとなってしまいます。そこで、continueやbreakの代替案として同じ処理を行なう方法をご紹介します。

3-1-1.処理を中断させたい場合はreturnで代用

forEachメソッドで処理を中断して次のループ処理を実行させるためにはreturnを使用します。

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// 偶数のみを出力
numbers.forEach(function(number){
     if(number % 2 !== 0){
          return;
     }
     console.log(number);
});

// ↓出力結果
// 0
// 2
// 4
// 6
// 8

returnを用いることでその時点でnumberが奇数の時はコールバック関数が終了され、numberを出力することなく次のコールバック関数が呼び出されます。よって、continueと同じ挙動となります。

3-1-2.処理自体を抜け出したい場合はfor文やsomeメソッドで代用

forEachメソッドで処理自体の抜け出しはできないため、for文やsomeメソッドで代用します。for文を用いた例は以下の通りです。

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// 3までを出力し4以降は出力させない
for(var i = 0; i < numbers.length; i++){
     if(numbers[i] === 4){
          break;
     }
     console.log(numbers[i]);
}

// ↓出力結果
// 0
// 1
// 2
// 3

またsomeメソッドで代用すると以下のように記述することができます。

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// 3までを出力し4以降は出力させない
numbers.some(function(number){
     if(number === 4){
          return true;
     }
     console.log(number);
});

// ↓出力結果
// 0
// 1
// 2
// 3

someメソッドは、配列の要素のうちコールバック関数に指定した条件を1要素でも満たす場合はtrueを返して、全ての要素が条件を満たさない場合のみfalseを返します。つまり、コールバック関数の条件を満たす要素が現れた時点でtrueを返してコールバック関数の呼び出し自体を終了する性質があるため、抜け出したい条件を指定する際にtrueを返してあげることで、配列のループ処理を抜け出すことができます。

3-2.他のメソッドを用いる方が適切な場面がある

配列に対して特定の処理を行いたい場合はその処理に適したメソッドが他に存在するため、forEachメソッドではない方が適切に記述できることがあります。その一例をご紹介します。

3-2-1.配列から特定の要素のみを取り出す場合はfindメソッドfilterメソッド

配列の中から特定の要素を取り出したい場合には、findメソッドやfilterメソッドを使うと良いです。findメソッドはコールバック関数に指定した条件に合致する最初の要素1つを取り出します。

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

var findNumber = numbers.find(function(number){
     return number === 3;
});

console.log(findNumber);

// ↓出力結果
// 3

// アロー関数を使うとさらにスッキリ記述できる
findNumber = numbers.find((number) => number === 5);

console.log(findNumber);

// ↓出力結果
// 5

filterメソッドはコールバック関数に指定した条件に合致する全ての要素を配列として返します。

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

var findNumbers = numbers.filter(function(number){
     return number % 2 === 0 ;
});

console.log(findNumbers);

// ↓出力結果
// [0, 2, 4, 6, 8]

// アロー関数を使うとさらにスッキリ記述できる
findNumbers = numbers.filter((number) => number % 2 !== 0);

console.log(findNumbers);

// ↓出力結果
// [1, 3, 5, 7, 9]

3-2-2.配列を加工して別の配列を作る場合はmapメソッド

配列の各要素を加工して別の配列を作りたい場合はmapメソッドを使うと良いです。mapメソッドは配列の各要素に対してコールバック関数で処理を行い、その結果を新しい配列として返します。

const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

const doubledNumbers = numbers.map(function(number){
     return number * 2 ;
});

console.log(doubledNumbers);

// ↓出力結果
// [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

// アロー関数を使うとさらにスッキリ記述できる
const squareNumbers = numbers.map((number) => number ** 2);

console.log(squareNumbers);

// ↓出力結果
// [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

4.最後に

forEachメソッドは配列の繰り返し処理を行なう際に便利なメソッドです。今回ご紹介したように様々な使い方ができる汎用的なメソッドですが、注意点も踏まえて使てみてください。

私たちは、全てのエンジニアに市場価値を高め自身の望む理想のキャリアを歩んでいただきたいと考えています。もし、今あなたが転職を検討しているのであればこちらの記事をご一読ください。理想のキャリアを実現するためのヒントが見つかるはずです。

コメント

26卒 新卒学生向け主催企業:株式会社ボールド
どんなIT企業なら理想のエンジニアになれるのか?

2時間でIT業界の全てが分かるOne dayインターン

26卒 新卒学生向け主催企業:株式会社ボールド
どんなIT企業なら理想のエンジニアになれるのか?

2時間でIT業界の全てが分かるOne dayインターン