この記事では、JavaScriptのアロー関数の構文について紹介します。フロントエンドの開発でフレームワークを使用するときに、JavaScriptの構文の知識は必ず役に立ちます。私自身も仕事でよく使うので今更ながら整理しようと思いました。
アロー関数はES6とも呼ばれるECMAScript 2015でJavaScriptに導入されました。コードの記述を簡潔にすることができる一方で、使用する上で注意しなければならない点もあります。thisキーワードの扱いはその中の一つでしょう。
目次
ES6以前の関数とアロー関数の比較
JavaScriptで関数を宣言して呼び出す標準的な方法は次のようになりますね。
この例は単純に文字列を返すだけの関数です。
関数式として次のように同じ関数を記述することもできます。
アロー関数を使用して上記の関数を書き直すと、次のようになります。
この例ではアロー関数を使うと次のようなメリットがあることが分かります。
- 関数の宣言が1行になった
- functionキーワードの記述がない
- returnキーワードの記述がない
- 中括弧{}の記述がない
JavaScriptでは、関数は「第一級オブジェクト」なので、関数を変数に格納し、それらを他の関数として引数として渡し、他の関数から値として返すことができます。アロー関数を使用しても、これらを実現することができます。
括弧なしの構文
上記の例では関数に引数がありません。このように引数がない場合、アロー関数を使う場合、「=>」の前に空の括弧()を記述する必要があります。これは引数が複数ある場合についても同様です。
ただし、引数が1つの場合は括弧を省略することができます。次の例を見てください。
もしデフォルト引数を指定する場合には、括弧をつける必要があるので注意してください。
暗黙の返値
関数内に式が1つしかない場合、中括弧{}とreturnキーワードを省略して、1行で記述できます。
この記述方法を知っておくと、コードをシンプルに書けるようになります。
例えば、動画配信サービスの開発で次のようなデータを扱うとしましょう。
配列ないのnameが動画のシリーズ名、likesがいいねの数です。アロー関数を使っていいねの数が多い順に並び替えてみます。
コード内で使用しているsortの詳細についてこちらで確認してみてください。
コードがシンプルになる反面、場合によってはコードの可読性にも注意した方が良いでしょう。
動画配信サービースで扱っている情報はシリーズ名といいねの数だけではありませんでした。あらすじ(synopsis)も含まれているようです。
このデータから次のようにして情報を抽出したいとします。
- シリーズ名のプロパティ名をnameでなくtitleとする
- シリーズ名とあらすじの情報のみ欲しい
この処理はmapを使うと次のように簡単に実現できます。
map内のアロー関数は一連のステートメントで展開され、最後にオブジェクトを返します。このような場合、アロー関数の中括弧を省略することはできません。
また、中括弧を使用しているので、暗黙の返値として扱うことができないため、returnキーワードを使用する必要があります。
ではシリーズ名のプロパティ名の変更のみ行う場合はどうでしょうか。次のサンプルコードを見てください。
これは間違い探しゲームではありません。
seriesList2の方は正常に動作していますが、seriesList1の方はうまくいっていないようです。
ここで注意しなくてはいけないのは、アロー関数の暗黙的な返値として、オブジェクトリテラルを返そうとしていることです。
この場合には、オブジェクトを丸括弧()で囲む必要があります。そうしないと、オブジェクトリテラルの中括弧とアロー関数本体の中括弧の判別ができなくなってしまうからです。
アロー関数に名前をつけることはできない
functionキーワードを使って無名関数を宣言するとき、通常は次のような記述になります。この例のように、functionキーワードと引数のリストの間に関数名がない関数を無名関数と呼びます。
アロー関数はすべて無名関数となります。
ときには無名関数を識別したいときもあるはずです。
ES6以降では、サンプルコードで示しているように、変数とメソッドはそのnameプロパティを使用して、無名関数の名前を推測できます。
ただし、このnameプロパティは、上記の例のように無名関数が変数に割り当てられている場合にのみ存在することに注意してください。
例えば、無名関数をコールバックとして使用する場合、無名関数がプロパティを利用きませんので、この便利な機能を使うことができなくなります。
このデメリットについては知っておいた方が良いでしょう。
アロー関数でのthisキーワードの扱い
まず通常のthisキーワードの動作について振り返るために、簡易的なタイマーの実装から始めます。
簡単のためにHTML、CSS、JavaScriptを一つのファイルに集約しています。また、動作確認するための最低限の実装にとどめています。
このファイルを.htmlファイルとして保存して、ブラウザで開くと次のようなカウントダウンタイマーが表示されるはずです。ボタンをクリックすると5から1へのカウントダウンが始まります。

17行目の.addEventListener()内のイベントハンドラ ーに注目してください。
アロー関数でなくfunctionキーワードを使用した通常の無名関数として記述しています。
18行目のthisは実際にクリックされるボタン要素を参照している必要があります。実際にconsole.log(this)で出力すると、ボタン要素が参照されていることが分かります。
もし、アロー関数に置き換えた場合にはどうなるでしょうか。
17行目をアロー関数に書き換えて、thisの内容を確認するために18行目と22行目に出力を追記しました。
この.htmlをブラウザで実行すると、カウントダウンタイマーは表示されても正常に動作しません。
18行目のconsole.log(this)の出力内容を確認してみましょう。thisはクリックしたボタン要素でなく、Windowオブジェクトを参照していると思います。
これは、アロー関数を使用した場合に、thisキーワードの値が親のスコープから継承されるために発生します。
このケースでは、17行目のアロー関数はグローバルスコープにあるメソッドへ引数として渡されていますので、アロー関数の内側のthisもグローバルスコープのWindowオブジェクトにバインドされているということになります。
したがって、19行目のthisがクリックされたボタン要素を参照させるようにするには、アロー関数でなく通常の関数を使用する必要があるということです。
このように全ての関数をアロー関数で置き換えられるわけではありません。
まとめ
この記事ではアロー関数について扱いました。
アロー関数を使用することで、暗黙の返値を使用してシンプルな記述にしたり、thisキーワードのバイディングの問題についても解決できます。
さらに記事で紹介した.sort()や.map()、.filter()、.reduce()などとも合わせて使用することができます。
ただし、アロー関数は通常のJavaScriptの関数に代わるものではなく、すべてのケースで有効な手段とはならないことに注意してください。
是非いろいろと試してみてください!
コメントを残す