Contents
アロー関数とは
アロー関数はECMAScript 2015(ES6)で定義された新しい構文です。
これまで、関数の定義にはfunction
を使ってきましたが、アロー関数を使うことで、より短い記述で関数を定義することができます。
const testFunc = function (a, b) { return a + b; }; console.log(testFunc(3, 4)); // 7
const testFunc = (a, b) => a + b; console.log(testFunc(3, 4)); // 7
同じ動作をする関数を、大きく短縮して記述することができました。function
をfucntion
などとミスタイプして、文法エラーになることもありません。
JavaScriptでは頻繁に関数を使うため、少しの差でも塵も積もればで省力化が期待できます。筆者もアロー関数を開発に取り入れて使っています。
アロー関数を使ったいくつかのパターン
コールバック関数を置き換える
const arr = [1, 2, 3, 4, 5]; // Before arr.forEach(function (num) { console.log(num); // 1, 2, 3, 4, 5 }); // After arr.forEach(num => { console.log(num); // 1, 2, 3, 4, 5 });
// Before window.setTimeout(function () { console.log('hoge'); }, 1000); // After window.setTimeout(() => { console.log('hoge'); }, 1000);
引数が複数の場合、または引数がない場合は、=>
の前に()
が必要です。
省略記法でさらに短く記述する
関数の中身がreturn
のワンセンテンスだけであれば、{}
もreturn
も省略できます。
const arr = [1, 2, 3, 4, 5]; // Before arr.filter(function (num) { return num > 3 }); // After arr.filter(num => num > 3);
1行でこれだけ短く書けるというのが、アロー関数の大きなメリットだと思います。
アロー関数の注意点
このように、プログラムを書く上での省力化に貢献してくれるアロー関数ですが、従来の関数の定義と比べると、いくつかの注意点があり、思わぬところでハマってしまう可能性もあります。
IEが未対応
IEはアロー関数に対応していないため、Webページ用のスクリプトでアロー関数を使う場合、BabelやTypeScriptでトランスパイルを行う必要があります。
IEなどの古いブラウザを相手にする場合でも、手元では積極的に最新の構文を取り入れて書くことができるので、多くのエンジニアが開発環境にトランスパイルを導入しています。
this
を束縛しない
アロー関数では文脈に応じてthis
の値を束縛する作用がないので、注意が必要です。
<button class="btn-bomb" data-log="bomb!">push</button>
例として、このボタンにclick
のイベントリスナを設定する場合を考えてみます。function
を使うと、以下のように書くことができます。
document.querySelector('.btn-bomb').addEventListener('click', function () { console.log(this.dataset.log); });
ボタンをclick
すると、data-log
属性に指定したbomb!
がコンソールに出力されます。コールバック関数内のthis
は、この場合、イベントリスナの仕掛け先である.btn-bomb
となります。
これを単純にアロー関数に置き換えると、以下のようになります。
document.querySelector('.btn-bomb').addEventListener('click', () => { console.log(this.dataset.log); });
ボタンを押すと、Uncaught TypeError: Cannot read property 'log' of undefined
とエラーが発生し、コンソールに目的の出力が得られません。その理由は、アロー関数を使うと、this
の中身が.btn-bomb
のbutton
要素にならないからです。
この場合は、例えば以下のような修正を行います。
const btn = document.querySelector('.btn-bomb'); btn.addEventListener('click', () => { console.log(btn.dataset.log); });
this
を使わずに、外側でボタンを参照した変数を作っておき、関数内でもその変数を参照しています。これであればthis
の影響を受けません。
このように、関数内でthis
が出てくる場合、function
の関数とアロー関数では動作が変わることがあるので、要注意です。
this
の中身がコロコロ変わる仕様について、「わかりづらい」と指摘され続けてきました。そこで、アロー関数では、
this
の中身を変更しないという仕様となったわけですが、その結果、function
の関数と動作の違いが生じています。あらゆるケースで単純にアロー関数に置き換えられるわけではないため、注意して使い分ける必要があります。
arguments
オブジェクトが使えない
function
の関数内では、特別なオブジェクトであるarguments
オブジェクトを利用することができます。arguments
オブジェクトには引数に関する情報が集められており、例えばarguments.length
で引数の数を調べることが可能です。
const func = function () { console.log(arguments.length); } func(0, 1, 2); // 3 func(0, 1, 2, 3); // 4
アロー関数では、このarguments
オブジェクトを利用することはできず、エラーとなります。
const func = () => { console.log(arguments.length); } func(0, 1, 2); // Uncaught ReferenceError: arguments is not defined
オブジェクトリテラルを省略記法でreturn
する場合は()
で括る
以下のようなケースを考えます。
const func = function () { return { a: 0, b: 1 }; }
これをアロー関数に置き換えてみます。関数の中身がreturn
1つなので、アロー関数ではreturn
も省略して記述できるはずです。
const func = () => { a: 0, b: 1 };
一見、問題なさそうに見えますが、これはUncaught SyntaxError: Unexpected token :
文法エラーとなります。
これは、波括弧{}
の部分が、関数の中身を定義する波括弧(() => {}
の{}
)と、オブジェクトリテラルの波括弧({ a: 0, b: 1 }
の{}
)の2通りの解釈ができてしまうからです。
この場合は、以下のように省略せずに記述するか、return
されるオブジェクトリテラルを()
で括る必要があります。
const func = () => { return { a: 0, b: 1 }; };
const func = () => ({ a: 0, b: 1 });
コンストラクタには使用できない
JavaScriptでは、関数がコンストラクタとなるので、function
を使って定義します。
const Human = function () {}; const human = new Human();
しかし、アロー関数で定義した関数は、コンストラクタになることができません。
const Human = () => {}; const human = new Human(); // Uncaught TypeError: Human is not a constructor
ES6では併せてclass
構文が導入されているので、代わりにclass
を使うことができます。
class Human {} const human = new Human();
まとめ
注意点も多いアロー関数ですが、省力化や可読性の向上と、大きなメリットのある構文です。
他人の書いたソースコードでは頻繁に見かけるようになりますので、ぜひ積極的に取り入れてみてください。