アロー関数を使って効率的にJavaScriptを記述する

シェアする

アロー関数とは

アロー関数は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

同じ動作をする関数を、大きく短縮して記述することができました。functionfucntionなどとミスタイプして、文法エラーになることもありません。

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でトランスパイルを行う必要があります。

JavaScriptでは、最新の構文で書かれたJavaScriptや、JavaScriptに色々な機能を追加した独自言語を使って書かれたソースファイルから、互換性の高いJavaScriptに変換することをトランスパイルと呼びます。
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-bombbutton要素にならないからです。

この場合は、例えば以下のような修正を行います。

const btn = document.querySelector('.btn-bomb');
btn.addEventListener('click', () => {
  console.log(btn.dataset.log);
});

thisを使わずに、外側でボタンを参照した変数を作っておき、関数内でもその変数を参照しています。これであればthisの影響を受けません。

このように、関数内でthisが出てくる場合、functionの関数とアロー関数では動作が変わることがあるので、要注意です。

元々、JavaScriptでは、文脈によって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 };
}

これをアロー関数に置き換えてみます。関数の中身がreturn1つなので、アロー関数では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();

まとめ

注意点も多いアロー関数ですが、省力化や可読性の向上と、大きなメリットのある構文です。

他人の書いたソースコードでは頻繁に見かけるようになりますので、ぜひ積極的に取り入れてみてください。

シェアする

フォローする