【JavaScript】アロー関数を使いスマートに関数を実装する手法を解説

Javascriptで開発を進めるうちに無名関数が乱立しすぎてソースコードが見づらくなっていませんか?

そんな時はアロー関数に書き換えることで、無名関数を簡潔に記述できます。

今回は、JavaScriptで無名関数を実装する際に覚えておきたい、アロー関数の書き方を詳しく解説していきます。無名関数と比較してどのような部分がスマートに書けるのか、サンプルコードで理解していただこうと思います。

また、アロー関数を使う際に気をつけるべきポイントも解説するので、ぜひプログラミングスキルの向上に役立ててください。


アロー関数とは?

アロー関数は、JavaScriptで用意されている関数の一つです。

アロー関数以外にも、JavaScriptでは普通の関数を定義できますが、具体的にどのような違いがあるのでしょうか。それを理解するためには、まずは「関数リテラル」と呼ばれる概念について理解することがポイントです。

関数リテラルとは?

リテラルとは、ソースコード上で数値・文字列・ブール値などを、直に記したものを指します。以下のソースコードをご覧ください。

let display_string = "本日は晴天なり";
let measured_value = 1221.432;
let isEnabled = false;

例えば、上記のソースコードでは「本日は晴天なり」「1221.432」「false」が、リテラルに該当します。リテラルは、変数に代入するときに記述されるのがほとんどです。

つまり、関数リテラル変数に代入できる関数ということになります。以下のサンプルコードは、関数リテラルの一例です。

// 関数リテラルの例
//(int型配列を引数として、配列に入っている値の合計値を計算)
let sum_proc = function(import_data) {
  let sum = 0;
  for (let data of import_data) {
    sum = sum + data;
  }
  return sum;
};

関数がイコールを介して変数に代入していることが見て取れます。この状態で関数を呼び出すためには、以下のようにコーディングします。

// 引数に渡すサンプルデータ
let import_data = [43, 543, 6, 34, 786, 67, 910];

// 関数リテラルを呼び出す文
let sum_value = sum_proc(import_data);

console.log(sum_value); // 結果:2389

従来の関数との違い

関数リテラルは、通常の関数の定義とは違って、関数の名前がなくてもよいのが大きな特徴です。このことから、関数リテラルは別名「無名関数」や「匿名関数」と呼ばれています。

関数リテラルとして実装された関数の場合は、関数の名前が存在しない代わりに、格納先の変数が関数の名前として利用できます。

アロー関数の便利な書き方

アロー関数は、関数リテラルのもう一つの書き方です。関数リテラルで書くと長ったらしくなるところを、アロー関数を利用すればより簡単に、関数を実装することができます。

アロー関数は、イコール(=)と大なり(>)を組み合わせた、矢のように見える記号(=>)を使って記述します。以下は、アロー関数の一例です。

// アロー関数による関数リテラルの定義
let join_proc = (input_array, delimiter_char) => {
  let result_str = "";
  for (let str of input_array) {
    result_str = result_str + str + delimiter_char;
  }
  result_str = result_str.slice(0, -1);
  return result_str;
}

let sample_str_array = ["abc", "def", "ghi", "jkl"];
console.log(join_proc(sample_str_array, ",")); // 結果:abc,def,ghi,jkl

特筆すべきポイントは、関数であることを示すキーワード「function」が書かれていないことです。

矢の記号(=>)を使えば関数リテラルであることが分かるため、わざわざ書かなくても良くなり、ソースコードの記述量を削減できます。関数内の処理の書き方や呼び出し方は、従来の関数リテラルと代わりません。

ブロックを省略できる

アロー関数は、場合によってさらに記述量を削減できます。1つ目は、ブロックを示す波カッコの省略です。

ブロックの中身が、1つの文で記述できるような単純なものであれば、以下のソースコードのように、波カッコをわざわざ記載する必要はありません。

// アロー関数の特徴:1行で記述できるならブロックを省略可能
let log_sample = (err_derail) => console.log("ERR" + err_derail);

戻り値が存在する場合は、戻り値であることを示すキーワード「return」も省略できます。簡単な計算を実施する関数を実装する場合は、アロー関数を使うことで計算式が見やすくなるのでおすすめです。

// アロー関数の特徴:1行で記述できるならreturnを省略可能
let value_average = (a, b, c) => (a + b + c) / 3;

引数を括るカッコを省略できる

2つ目は、引数をくくっているカッコの省略です。

引数が1個のみであるならば、カッコを省略して以下のソースコードのように記載できます。

// アロー関数の特徴:引数1個だけならカッコを領略可能
let display_fav_food = food_name => console.log("I like " + food_name);

一方、引数が2個以上ある場合はカッコを省略できません。また、引数がない場合も省略せずに、カッコのみを書かなければならないことに注意してください。

// アロー関数の特徴:引数が存在しないときもカッコは表記する
let call_hello = () => console.log("Hello!");

アロー関数を使用する際の注意点

先述したように、関数リテラルをアロー関数の形式で置き換えれば、ソースコードの量を削減できます。

一方で、使い方に注意しないとバグを生んでしまいかねません。ここでは、アロー関数を利用する上で注意すべきポイントを4つ解説します。

thisのスコープ

1つ目は、thisの挙動が通常の関数リテラルと異なることです。thisとは、オブジェクトを定義したときに利用できる、オブジェクト自身の情報が含まれるキーワードです。例えば、以下のソースコードをご覧ください。

let greeting = function () {
  console.log(this.word);
}

let greeting_AM = {
  word: "Good morning",
  greet: greeting
}

let greeting_PM = {
  word: "Good evening",
  greet: greeting
}

greeting_AM.greet(); // 結果:Good morning
greeting_PM.greet(); // 結果:Good evening

1行目で定義した関数リテラルをオブジェクトに含むことで、2行目のthis.wordが初めて参照できるようになります。

上記サンプルコードの場合は、メソッド呼び出し時のオブジェクトに含まれているプロパティを参考するため、greeting_AMであれば「Good morning」と出力されます。

次に、サンプルコード1行目の関数リテラルをアロー関数に置き換えて再実行してみましょう。両方とも「undefined」とコンソールに出力されたでしょうか。

アロー関数で定義した場合は、thisの中身がオブジェクトに関連しなくなります。もし、オブジェクトに外部の関数リテラルを含む場合は、thisの挙動に十分気を配るようにしましょう。

オブジェクトリテラルを返す際には括弧が必要

2つ目は、戻り値がオブジェクトリテラルの場合です。たとえ1行で表現できるとしても、オブジェクトリテラルを戻り値として返す場合は、特別にカッコで囲む必要があります。サンプルコードを以下に示します。

// オブジェクトリテラルが戻り値の場合
// 特例として丸カッコでオブジェクトリテラルを囲みましょう
let make_object = () => ({sample_key: 124});

prototypeプロパティが存在しない

3つ目は、prototypeプロパティが存在しないことです。

関数リテラルを格納している変数は、prototypeと呼ばれるプロパティを参照できます。一方、アロー関数で記載された場合は参照できません。

以下のサンプルコードを実行しても分かるように、prototypeプロパティを参照しても「undefined」が返されることが分かります。

let Hoge = function() {
  console.log("hogehoge");
}

let Fuga = () => console.log("fugafuga");

console.log(Hoge.prototype); // 結果:{constructor: ƒ}
console.log(Fuga.prototype); // 結果:undefined

argumentsの取得に工夫が必要

4つ目は、argumentsオブジェクトを保持していないことです。

argumentsは、関数内で参照できる、引数の情報が含まれるオブジェクトです。アロー関数で定義された関数リテラルは、argumentsオブジェクトを持っていません。

その代わりとして、可変長引数で実装することにより、argumentsと同じような処理を実装できます。サンプルコードは、以下の通りです。

let calc_average = (...data_list) => {
  let sum = 0, list_count = 0;
  for (let data of data_list) {
    sum += data;
    list_count++;
  }
  return sum / list_count;
}

console.log(calc_average(1, 3, 5, 7, 9)); // 結果:5

お仕事の途中ですが、少し一休みして、転職独立について考えてみませんか🙌?

現役エンジニアが選ぶおすすめの転職エージェント11選【成功談・失敗談もあります】

レバテックフリーランスの評判ってどう?【現役エンジニアが徹底解説します】

MidWorks(ミッドワークス)の評判ってどう?【現役エンジニアが徹底解説します】

日々の業務に追われて自分を見失わないよう、
定期的にキャリアを振り返るようにしておきましょう🤲

最後に

さて、ここまでJavascriptのアロー関数の便利な使い方や注意ポイントについて解説してきましたがいかがでしたか?

関数定義を簡略化できる便利なアロー関数ですが、通常の関数と同じように使っていると、ふとした時に思わぬバグに出くわしてしまいます。

アロー関数を使用する際の注意ポイントとしては、最後にご紹介した4つを覚えておけば概ね問題ありませんので、ぜひ頭の片隅にでも置いておいてくださいね。

このブログを通じて少しでも「傍(はた)を楽(らく)にする」ことができていれば嬉しく思います。

最後まで読んで頂きありがとうございました。