こんにちは、かつコーチです。
前回は関数の基本的な作り方と、引数・戻り値について解説しました。
今回は、モダンなJavaScriptのコードで頻繁に登場する「アロー関数」を解説します。
map や filter のコールバックとしてもすでに何度か登場していた書き方なので、ここでしっかり仕組みを理解しておきましょう。
アロー関数とは?
function文をより短く書ける記法
アロー関数(Arrow Function) とは、=> という矢印のような記号を使って関数を書く記法です。
ES2015(ES6)で導入され、通常の function 文をより短く書けるのが特徴です。
// function式
const add = function (a, b) {
return a + b;
};
// アロー関数
const add2 = (a, b) => {
return a + b;
};
console.log(add(2, 3)); // 5
console.log(add2(2, 3)); // 5
見た目はかなり違いますが、基本的にはどちらも「同じ処理をする関数」を作っています。
なぜアロー関数が広く使われているのか
アロー関数がここまで普及した理由は、大きく2つあります。
- 短く書ける:特にコールバック関数として渡すときにコードがすっきりする
thisの挙動が分かりやすい:通常の関数と異なり、アロー関数は自分自身のthisを持たない
1つ目は前回・前々回の記事で map((item) => item * 2) のような形で実際に体験済みだと思います。
2つ目の this については、この記事の後半で詳しく解説します。
アロー関数の書き方バリエーション
基本の書き方
まずは基本形からです。
引数を ( ) で囲み、=> の後に { } で処理を書きます。
const greet = (name) => {
return `こんにちは、${name}さん!`;
};
console.log(greet("かつコーチ")); // こんにちは、かつコーチさん!
省略記法:引数が1つのとき
引数が1つだけの場合、( ) を省略できます。
const double = (num) => num * 2; // 引数が1つなら丸括弧を省略できる
// const double = num => num * 2; と書いても同じ
console.log(double(5)); // 10
ただし、引数が0個や2個以上の場合は ( ) を省略できません。
const sayHi = () => "hi"; // 引数0個は () が必要
const add = (a, b) => a + b; // 引数2個も () が必要
省略記法:処理が1行のとき(暗黙のreturn)
処理内容が return する値だけの1行で済む場合、{ } と return を省略できます。
// 省略しない書き方
const square = (num) => {
return num * num;
};
// 省略した書き方(暗黙のreturn)
const square2 = (num) => num * num;
console.log(square(4)); // 16
console.log(square2(4)); // 16
これは「式(1つの値を返す処理)を { } なしで書くと、その式の結果が自動的に戻り値になる」というルールです。
複数行の処理が必要な場合や、if 文などを含む場合は { } と return を省略できません。
つまずきやすいポイント:オブジェクトを返すときの落とし穴
{ } がブロックと勘違いされてしまう話
私がアロー関数を学び始めたころ、オブジェクトを直接返そうとして詰まった ことがあります。
❌ Before:オブジェクトリテラルをそのまま返そうとする
const createUser = (name, age) => { name: name, age: age };
console.log(createUser("かつコーチ", 30));
// 期待:{ name: "かつコーチ", age: 30 }
// 実際:undefined(エラーにならないので気づきにくい)
このコードは、{ } が「オブジェクトリテラル」ではなく「関数の処理ブロック」として解釈されてしまいます。
その結果、name: name は「name というラベルの付いた文」、age: age は単なる式として扱われ、return もないため undefined が返ってしまいます。
エラーにならずに静かに undefined を返すため、私は「なぜオブジェクトが返ってこないんだろう」としばらく気づけませんでした。
✅ After:( ) でオブジェクトリテラルを囲む
const createUser = (name, age) => ({ name: name, age: age });
console.log(createUser("かつコーチ", 30));
// { name: "かつコーチ", age: 30 }
先頭の { を ( ) で包んであげることで、JavaScriptに「これは処理ブロックではなく、オブジェクトリテラルですよ」と明示的に伝えられます。
「アロー関数でオブジェクトを直接返すときは丸括弧で包む」というのは、覚えておかないと必ず一度は踏む落とし穴なので、ここでしっかり押さえておきましょう。
アロー関数と this の違い
通常の関数との決定的な違い
アロー関数のもう1つの重要な特徴が、自分自身の this を持たない ことです。
通常の function は呼び出され方によって this の中身が変わりますが、アロー関数は「自分が定義された場所の外側の this」をそのまま使います。
const timer = {
seconds: 0,
start: function () {
// 通常のfunctionをsetIntervalに渡すと、thisがずれてしまう
setInterval(function () {
this.seconds++; // このthisはtimerオブジェクトを指さない
console.log(this.seconds); // NaN
}, 1000);
},
};
const timer = {
seconds: 0,
start: function () {
// アロー関数なら、外側(start内)のthisをそのまま使ってくれる
setInterval(() => {
this.seconds++; // このthisはtimerオブジェクトを指す
console.log(this.seconds); // 1, 2, 3, ...
}, 1000);
},
};
this の挙動は最初は理解しづらいポイントですが、「コールバック関数の中で this を使いたいときは、基本的にアロー関数を使う」と覚えておけば、実務ではほとんど困りません。
どちらを使うべきか
初心者のうちは、以下のように使い分けを覚えておくと迷いにくいです。
| 場面 | おすすめ |
|---|---|
map ・ filter などのコールバック関数 | アロー関数 |
| オブジェクトの中で定義するメソッド | 通常の function (もしくは省略記法) |
this を意識する必要がある処理 | 状況に応じて使い分ける |
「迷ったらまずアロー関数、this の挙動がおかしいと感じたら通常の function を検討する」くらいの感覚で始めても十分です。
まとめ
この記事のポイント
- アロー関数は
=>を使って関数を短く書ける記法 - 引数が1つなら
( )を、処理が1行なら{ }とreturnを省略できる - オブジェクトを直接返すときは
( )で囲まないと、処理ブロックと誤認識されてundefinedになる - アロー関数は自分自身の
thisを持たず、外側のthisをそのまま引き継ぐ - コールバック関数として使う場面ではアロー関数が特に活躍する
次に読むべき記事
アロー関数まで理解できれば、モダンなJavaScriptの基本文法はかなり身についてきています。
次は、文字列の中に変数を埋め込める「テンプレートリテラル」を使いこなしていきましょう。
→ 次の記事:テンプレートリテラルで文字列を扱う