[PR] 本記事にはプロモーションが含まれています。

【JavaScript】アロー関数(=>)とは?function からの書き換え方と、this など function との違い

JavaScript

JavaScriptのコードを読んでいると、map や filter の中に line => line.trim() のような書き方がよく出てきます。これは「アロー関数」と呼ばれる、関数の短い書き方です。

C言語を長く書いてきた私には、関数をその場で作って引数に渡す書き方そのものが、最初はなじみのないものでした。C言語でいえば、qsort に比較関数のポインタを渡すのに近く、その関数を別の場所で定義せず、その場で書いてしまうイメージです。

この記事では、function を使った書き方から順に短くしてアロー関数の形を理解し、function との違いも確かめます。

アロー関数とは

アロー関数は、ES2015(ES6)で追加された関数の書き方です。=> が矢印(アロー)に見えるので、こう呼ばれます。function より短く書けることに加えて、関数の中の this の扱いが違うという特徴があります(後で説明します)。

そこで、同じ「数を2倍にする」関数を、いろいろな書き方で並べてみます。

JavaScript
// ① function で宣言する(関数宣言)
function double1(n) {
  return n * 2;
}

// ② 名前のない関数を変数に入れる(関数式)
const double2 = function (n) {
  return n * 2;
};

// ③ アロー関数
const double3 = (n) => {
  return n * 2;
};

// ④ アロー関数で省けるものを省いた形
const double4 = n => n * 2;

console.log(double1(5), double2(5), double3(5), double4(5)); // 10 10 10 10

どれも同じ結果になります。②の function を消して => を置くと③になり、③からカッコや return を省くと④になります。

map の中で書き換えてみる

アロー関数がいちばんよく使われるのは、map や filter のように、関数を引数として渡す場面です。ここでは、配列の文字列から前後の空白を取り除く処理を、順に短くしていきます。

第1段階:function で書く

JavaScript
const lines = ['  りんご ', 'みかん  ', ' ぶどう'];

const trimmed = lines.map(function (line) {
  return line.trim();
});

console.log(trimmed); // ['りんご', 'みかん', 'ぶどう']

map は、配列の要素を1つずつ line に入れて関数を呼び、戻り値を集めた新しい配列を作ります。trim() は、文字列の前後の空白を取り除くメソッドです。

第2段階:function を => に置き換える

JavaScript
const trimmed = lines.map((line) => {
  return line.trim();
});

function という言葉がなくなり、引数の (line) の後ろに => が入りました。function line => のように両方を書くのではなく、function の代わりに => を使う、と考えると分かりやすいです。

第3段階:引数のカッコを省く

JavaScript
const trimmed = lines.map(line => {
  return line.trim();
});

引数が1つだけのときは、引数を囲む () を省けます。

第4段階:{} と return を省く

JavaScript
const trimmed = lines.map(line => line.trim());

関数の中身が「式を1つ返すだけ」のときは、{} と return も省けます。式の値がそのまま戻り値になります。実際のコードでよく見るのは、この形です。

同じように4段階で短くしていく流れを、filter を例に「filterメソッドの書き方」でも紹介しています。

省略のルールと注意点

引数の数でカッコの要る・要らないが変わる

JavaScript
const hello = () => 'Hello';        // 引数が0個:() は省けない
const square = n => n * n;          // 引数が1個:() を省ける
const add = (a, b) => a + b;        // 引数が2個以上:() は省けない
const greet = (name = 'ゲスト') => `こんにちは、${name}さん`; // デフォルト値を使うときも () が必要

引数が1つでも () を付ける書き方は正しく、コードを自動で整える Prettier も、初期設定では (n) => ... のようにカッコを付けます。バッククォートを使った文字列は「文字列の ‘ と ” と ` の違い」で紹介しています。

オブジェクトを返すときは () で囲む

{} と return を省いた形でオブジェクトを返すときは、注意が必要です。{ が「関数の中身の始まり」と受け取られてしまうので、オブジェクトを () で囲みます。

JavaScript
const names = ['りんご', 'みかん'];

// 間違い:{ name: n } が関数の中身と受け取られ、undefined が返る
const ng = names.map(n => { name: n });
console.log(ng); // [undefined, undefined]

// 正しい:() で囲む
const ok = names.map(n => ({ name: n }));
console.log(ok); // [{ name: 'りんご' }, { name: 'みかん' }]

function とアロー関数の違い

アロー関数は function を短くしただけのものではなく、動きが違うところがあります。

項目functionアロー関数
中の this呼び出し方で決まる外側の this をそのまま使う
new での呼び出しできるできない(TypeError)
arguments使える使えない(代わりに …args を使う)
定義より前での呼び出し関数宣言ならできるconst に入れた場合はできない

this の違い

いちばん大きな違いが this です。アロー関数は自分の this を持たず、外側の this をそのまま使います。そのため、メソッドの中でタイマーなどの関数を渡すときは便利ですが、メソッドそのものをアロー関数で書くとうまく動きません。

JavaScript
const timer = {
  seconds: 0,

  // 動く:メソッドの中のアロー関数は、start の this(timer)をそのまま使う
  start() {
    setInterval(() => {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  },

  // 動かない:メソッド自体をアロー関数にすると、this が timer を指さない
  reset: () => {
    this.seconds = 0; // timer.seconds は 0 に戻らない
  },
};

start の中の setInterval に function を渡すと、その中の this は timer を指さず、秒数が増えません。逆に、reset のようにオブジェクトのメソッドをアロー関数で書くと、this がオブジェクトを指さないので、メソッドはふつうの書き方(reset() { ... })にします。

クラスのメソッドの中で filter を使う例は、「filterメソッドの書き方」の「中で this を使うときはアロー関数にする」でも紹介しています。

定義より前で呼べるか

function で宣言した関数は、ファイルの上のほうからでも呼べます。const に入れたアロー関数は、その行より前では呼べません。

JavaScript
sayHello(); // OK:関数宣言は先に呼べる

function sayHello() {
  console.log('Hello');
}

sayBye(); // ReferenceError:const の行より前では呼べない

const sayBye = () => {
  console.log('Bye');
};

どちらを使えばいい?

  • map、filter、forEach、setTimeout などに渡す短い関数 → アロー関数が向いている
  • オブジェクトやクラスのメソッド → reset() { ... } のようなメソッドの書き方
  • new で使う関数や、中で this を切り替えたい関数 → function
  • ファイルのどこからでも呼ぶ普通の関数 → 関数宣言でも、const とアロー関数でもよい(プロジェクトの書き方に合わせる)

まとめ

  • アロー関数は、function の代わりに => を使う関数の書き方(ES2015で追加)
  • 引数が1つなら () を、中身が式を返すだけなら {} と return を省ける
  • オブジェクトを返すときは ({ ... }) のようにカッコで囲む
  • this は外側のものを使う。メソッドの中で渡す関数には便利だが、メソッドそのものには使わない

この記事のコードは、ブラウザのコンソールやCodePenに貼ればすぐに試せます。アロー関数は、画面の要素にクリックの処理を付けるときにもよく使います。要素の取得方法は「querySelectorで使えるCSSセレクターの書き方」で紹介しています。

ほかの開発・プログラミングの記事は、開発・プログラミングメモの目次から、テーマ別に探せます。

このブログは、にほんブログ村と人気ブログランキングに参加しています。記事が役に立ったら、下のランキングのバナーのどれかを押して応援してもらえると励みになります。

ブログランキング・にほんブログ村へにほんブログ村

サーバー構築・運用ランキング プログラムランキング

JavaScript
watasoftdevをフォローする

コメント