【高階関数】forEachメソッドについて解説 | GASおじさんのブログ
GASの基本

【高階関数】forEachメソッドについて解説

forEach GASの基本

forEachメソッド

forEachメソッドの概要

forEachメソッドは引数にコールバック関数を指定する高階関数です。

「コールバック関数」とか「高階関数」というとなんだか難しそうに聞こえますが、なんてことはない、ただのfor文です。

たとえば以下は配列usersから1個ずつ要素を取り出してコールバックの引数userに代入して繰り返し処理をするだけのfor文です。

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  users.forEach(function(user) {
    console.log(user);
  });
}

こちらの実行結果は以下の通りです。

ただのfor文ですね。

つまりこれは、以下のfor-of文と同義ということです。

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  for (const user of users) {
    console.log(user);
  }
}

なお、以下の記事でも紹介しているとおり、高階関数のコールバックはアロー関数で書くのがオススメです。

forEachのコールバック関数をアロー関数で書き換えると以下のようになります。

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  users.forEach((user) => {
    console.log(user);
  });
}

forEachメソッドの特徴

コールバックの第2引数で配列のインデックス番号を受け取ることができます。

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  users.forEach((user, index) => {
    console.log(user);
  });
}

こちらの実行結果は以下の通り。

forEachを使う際の注意点

forEachではループを途中で終了(break)することやスキップ(continue)することができません。

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  users.forEach((user, index) => {
    if (index == 1) break; // エラーになります 
    console.log(user);
  });
}
function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  users.forEach((user, index) => {
    if (index == 1) continue; // エラーになります 
    console.log(user);
  });
}

breakやcontinueを使いたい場合はfor-ofやforループを使う必要があります。

いろいろなfor文の書き方を比較してみよう

配列の要素を1個ずつ取り出すfor-of文

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  for (const user of users) {
    console.log(user);
  }
}

まずは一番読みやすいfor-of文。基本的にはこれを使うことが一番多いと思います。

配列のインデックス番号を取り出すfor-in文

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  for (const i in users) {
    const user = users[i];
    console.log(user, i);
  }
}

これはあまり使わないですね。特に上記のように繰り返す対象が配列の場合は使うことはないでしょう。ただし、繰り返す対象がオブジェクトの場合は使うことがあるので、仕組みは知っておいた方がいいです。

数字をインクリメントするfor文

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  for (let i = 0; i < users.length; i++) {
    const user = users[i];
    console.log(user, i);
  }
}

これは「従来のfor文」ですね。C言語やJava、C++などの多くのプログラミング言語で同じ形式のforループが使われてきたため、「従来のfor文」や「Cスタイルのfor文」などと呼ばれることもあります。

配列の要素とインデックス番号を一緒に取り出すforEach

function myFunction() {
  const users = ['佐藤', '鈴木', '高橋'];
  users.forEach((user, i) => {
    console.log(user, i);
  });
}

そして今回の主役のforEachです。これは要素とインデックス番号を同時に取得したいときに使うことになります。

forEachの使用例

私がforEachを使う場面を紹介します。

以下のようなスプレッドシートがあったとします。

このUsersシートから二次元配列を取得して、それをオブジェクトの配列に変換したいときに以下のスクリプトを使います。

function getAllUsers() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getSheetByName('Users');
  const values = sheet.getDataRange().getValues();
  const columns = values.shift();

  const users = [];
  for (const value of values) {
    const user = {};
    columns.forEach((column, index) => {
      user[column] = value[index];
    });
    users.push(user);
  }

  return users;
}

10〜12行目でforEachを使っています。

このgetAllUsers関数を実行すると以下のオブジェクトの配列が取得できます。

[ { id: 'U001',
    last_name: '佐藤',
    first_name: '一郎',
    email: 'hagazu@boxfi.uk',
    wants_mail: true },
  { id: 'U002',
    last_name: '鈴木',
    first_name: '亮太',
    email: 'sagibaso@macr2.com',
    wants_mail: true },
  { id: 'U003',
    last_name: '高橋',
    first_name: '美奈子',
    email: 'yametaru@haren.uk',
    wants_mail: true },
  { id: 'U004',
    last_name: '田中',
    first_name: '卓郎',
    email: 'yopyarogya@hamham.uk',
    wants_mail: false },
  { id: 'U005',
    last_name: '伊藤',
    first_name: '莉沙',
    email: 'pyatenomi@eripo.net',
    wants_mail: false },
  { id: 'U006',
    last_name: '渡辺',
    first_name: '奈緒美',
    email: 'neyupyo157@cream.pink',
    wants_mail: false },
  { id: 'U007',
    last_name: '山本',
    first_name: '彩花',
    email: 'monyowabu@momoi.uk',
    wants_mail: false },
  { id: 'U008',
    last_name: '中村',
    first_name: '浩輔',
    email: 'gyopi754@eay.jp',
    wants_mail: false },
  { id: 'U009',
    last_name: '小林',
    first_name: '幸',
    email: 'simyu346@magim.be',
    wants_mail: false },
  { id: 'U010',
    last_name: '加藤',
    first_name: '次郎',
    email: 'mike284@instaddr.uk',
    wants_mail: false } ]

こちら詳しくは以下のUdemyで解説していますので、気になる場合はぜひご参考ください。

GASで超実用的なシステムを神速開発するためのスキル習得講座【Google Apps Script実践】
GASおじさんによる日本一わかりやすいGASの授業、第2弾!Gmailやスプレッドシート、ドキュメントなど様々なGoogleアプリを自在に連携し、現場で即活用できる実用的なシステムを神速で開発!明日から役立つ実践的なスキルを身につけよう!

まとめ

ECMAScript 2015以降、for-of文が使えるようになったので、昨今ではforEachはあまり使われなくなりました。

可読性の観点からもfor-ofを使う方が推奨されるため、今さらforEachを学ぶことに意義を感じられないかもしれません。

しかし、for-of文では配列の要素しか取り出せません。インデックス番号も一緒に取得したいときはforEachのほうが便利です。状況によってはforEachを使うこともあるので、しっかり学んでおいたほうがいいでしょう。

また、mapやfilterなど他の高階関数を学ぶにあたっては、まずこのforEachを習得しておくと理解が進みやすいため、ぜひforEachの仕組みを根本から理解するようにしましょう。

当記事では最小限の説明にとどめていますので、ぜひChatGPTに次のような質問を投げかけてみて、理解を深めてみてください。

JavaScriptのforEachについて教えてください。

forEachとfor-ofはどのように使い分けるべきですか?

高階関数ってなんですか?

コールバック関数ってなんですか?

コメント

タイトルとURLをコピーしました