順番に読み進めながら学べます

アロー関数 — 省略形とオブジェクトを返す書き方

JavaScript のアロー関数を基礎から学びます。=> による書き換え、引数の丸括弧と本体の波括弧を省く省略形、オブジェクトを返すときの丸括弧、複数行のブロック本体を扱います。

配列の要素を 1 件ずつ整形するような短い処理でも、関数式で書くと function と波括弧と return が毎回並び、処理の中身が記号に埋もれます。

この記事では、=> で関数を作るアロー関数と、丸括弧や波括弧を省ける省略形を扱います。

同じ処理を短く書く — アロー関数の基本形

購入金額からポイント付与額を出すように、受け取った値を 1 つ計算して返すだけの関数はよくあります。それでも function の語と波括弧と return を毎回書くため、関数式が並ぶと計算の中身より書き方の部品のほうが目立ちます。

アロー関数=> を使って関数を作る書き方)は const 名前 = (引数) => { 本体 }; と書きます。function の語を消し、引数の並びと本体の間に => を置いた形で、関数式と同じように変数へ代入して呼び出します。

// これまでの書き方: 関数を値として変数に代入する関数式
const pointBack = function (price) {
  return price * 0.02;
};

// アロー関数
const pointBackArrow = (price) => {
  return price * 0.02;
};

console.log(pointBack(3200));        // 64
console.log(pointBackArrow(3200));   // 64
console.log(typeof pointBackArrow);  // function
関数式からアロー関数への書き換え
関数式const 名前 =function (price){ returnprice * 0.02 }3200 で64 が返るアロー関数const 名前 =(price) =>{ returnprice * 0.02 }3200 で64 が返るここだけ違う
代入する形と本体はそのままで、真ん中の部品だけが変わります。function の語が消え、引数の後ろに => が付きます

比較のため pointBackpointBackArrow に名前を分けていますが、どちらも typeoffunction で、引数の受け取り方も return の働きも同じです。この基本形から、条件がそろうと括弧や return を省けます。

サブスクの年額を出す関数式 yearlyFee をアロー関数に書き換えます。standardMonthly と premiumMonthly も宣言済みです。

① yearlyFee を、動きを変えずにアロー関数にしてください。

② スタンダードとプレミアムの年額を、それぞれ「スタンダード: ◯ 円」「プレミアム: ◯ 円」と表示してください。

③ ② の 2 つの差額を「差額: ◯ 円」と表示してください。

(正しく実行できれば解説が表示されます)

JavaScript / TypeScript エディタ

コードを実行してください

括弧と return を省く — 1 引数と暗黙の return

受け取った金額に送料を足す、5000 円以上かを判定するといった、式 1 つで済む処理があります。基本形のアロー関数だと 1 行の計算にも波括弧と return を含めて 3 行を使い、こうした関数が並ぶと行の大半を括弧と return が占めます。

引数がちょうど 1 つなら、引数を囲む丸括弧を省けます。さらに本体が式 1 つだけなら、波括弧と return も省けます。このとき働くのが暗黙の return(本体の式の値がそのまま戻り値になる決まり)です。

// 基本形: 引数の丸括弧・本体の波括弧・return をすべて書く
const withFee = (price) => {
  return price + 500;
};

// 省略形
const withFeeShort = price => price + 500;
const isFreeShipping = total => total >= 5000;

console.log(withFee(1200));          // 1700
console.log(withFeeShort(1200));     // 1700
console.log(isFreeShipping(4800));   // false
省略できる部分は上から順に増える
(price) => {return price + 500; }省略なしの形price => {return price + 500; }引数が 1 つなら丸括弧を省けるprice =>price + 500式 1 つなら波括弧とreturn も省ける
3 つの段階は書き方が違うだけで、同じ計算をしています。1200 を渡せば、どの段階でも 1700 が返ります

isFreeShipping の本体は比較の式 1 つなので、4800 を渡すと 4800 >= 5000 の結果の false がそのまま戻ります。暗黙の return で戻るのは式の値なので、計算でも比較でも同じ形で書けます。

引数が 0 個や 2 個のときは丸括弧を省けません

() => 式 のように引数が無い場合と、(price, rate) => 式 のように 2 つ以上ある場合に丸括弧を外すと、SyntaxError になって実行そのものが始まりません。引数を後から増やすときは、丸括弧の付け直しが要ります。引数が 1 つでも (price) => 式 と丸括弧を残して書けます。

配送の見積もりで使う関数を、式 1 つの本体で作ります。shippingFee と boxCount は宣言済みです。

① 送料を受け取り、10% 引き(切り捨て)の金額を返す discountFee を 1 行で書いてください。

② 送料と箱数を受け取り、送料の合計を返す totalFee を 1 行で書いてください。

③ ① を呼んで「割引後: ◯ 円」と表示してください。

④ ① の結果を ② に渡して「割引後の合計: ◯ 円」と表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

オブジェクトを返す — 丸括弧で包む書き方

1 件のデータを画面用の形に整えるとき、返したいのは 1 つの数値ではなく、複数のキーを持つオブジェクトです。ところが省略形のまま => の後ろに波括弧を書くと、オブジェクトではなく undefined が返ってきます。

=> の後ろに書いた波括弧はブロック本体(文をいくつでも並べられる領域)として読まれ、オブジェクトとしては読まれません。オブジェクトを返すときは (name) => ({ name: name }) のように丸括弧で包み、波括弧を式として読ませます。

// 波括弧をそのまま書くと、ブロック本体として読まれる
const toBadge = (name) => { label: name };
console.log(toBadge("ワイヤレスマウス"));      // undefined

// 丸括弧で包むと、波括弧がオブジェクトとして読まれる
const toCard = (name, stock) => ({ name: name, inStock: stock > 0 });
const card = toCard("ワイヤレスマウス", 4);
console.log(JSON.stringify(card));           // {"name":"ワイヤレスマウス","inStock":true}
console.log(card.inStock);                   // true
波括弧が本体になるか、オブジェクトになるか
(name) =>{ label: name }波括弧はブロック本体として読まれるreturn が書かれていないundefined が返る(name) =>({ label: name })丸括弧の中は式として読まれる波括弧がオブジェクトになるオブジェクトが返る
同じ波括弧でも、丸括弧で包むかどうかで読まれ方が変わります。包まない波括弧は、return の無いブロック本体として扱われます

キーを 2 つ以上書いた { name: name, inStock: true } は文として読めないため、SyntaxError で実行が始まりません。キーが 1 つのときは文として読めてしまい、エラーにならず undefined が返るので、表示するまで気づきにくくなります。

見積もりを作ります。orderTotals と freeLine は宣言済みで、freeLine 未満は送料 500 円です。

① 金額から total、shippingFee の順にキーを持つオブジェクトを返す toQuote を 1 行で書いてください。

② 1 件目を JSON.stringify で表示してください。

③ 2 件目の「支払額: ◯ 円」(金額 + 送料)を表示してください。

④ 2 件の「送料合計: ◯ 円」を表示してください。

JavaScript / TypeScript エディタ

コードを実行してください

処理が複数行になるとき — ブロック本体と return

返品の受付期限のように、返す文言を決める前に途中の日数を計算したり、条件で分けたりする処理があります。式 1 つの省略形には、途中の値を置いておく場所も、条件ごとに返す値を変える場所もありません。

ブロック本体には constif の文を並べられますが、暗黙の return は働かないため、値を返すには return を書きます。return は 1 つの関数に複数書け、先に実行された行で関数が終わります

// 式 1 つの本体: 式の値がそのまま戻る
const shortMessage = (days) => `購入から ${days} 日`;
console.log(shortMessage(12));           // 購入から 12 日

// ブロック本体: 途中の値を作り、条件ごとに return する
const returnMessage = (days, isOpened) => {
  const limit = isOpened ? 7 : 14;
  if (days > limit) {
    return "受付は終了";                  // ここで関数が終わる
  }
  return `あと ${limit - days} 日`;
};
console.log(returnMessage(12, false));   // あと 2 日
console.log(returnMessage(12, true));    // 受付は終了

// return が無いと undefined
const brokenMessage = (days) => { `あと ${days} 日`; };
console.log(brokenMessage(12));          // undefined
開封済みかで届く return が変わる
returnMessage(12, false)limit は 1412 > 14 は不成立最後の returnまで進むreturnMessage(12, true)limit は 712 > 7 が成立if の中の returnで終了
開封済みの呼び出しだけが if の中の return に届きます。そこで関数が終わり、後ろの return には進みません

条件に合わない場合を先に return で返しておくと、その後ろの行には通常の場合の処理だけを書けば済みます。下の表は、本体の書き方ごとに、呼び出し側へ返る値を並べたものです。

本体の書き方本体の中で起きること呼び出し側に返る値
days => 式式の値がそのまま戻る購入から 12 日
(days, isOpened) => { 文と return }実行された return の値が戻るあと 2 日 / 受付は終了
days => { 式だけ }式は評価されるが外へ渡らないundefined

this の扱いが通常の関数と違います

オブジェクトのメソッドの中では this(そのメソッドを呼び出したオブジェクト自身を指す語)が使えます。アロー関数はこの this を自分では持たず、外側で決まっているものをそのまま使います。この違いはクラスを扱うオブジェクト指向の章で改めて確認します。

在庫の補充数をロット単位に合わせて計算します。targetStock、currentStock、lotSize は宣言済みです。

① 目標在庫・現在の在庫・入り数を受け取るアロー関数 planRestock を、ブロック本体で書いてください。

② 本体で不足数を求め、ロット単位に切り上げた個数を返してください(不足が無ければ 0)。

③ 現在の在庫で呼び出し、「補充: ◯ 個」と表示してください。

④ 在庫が目標と同じ場合も、同じ形で表示してください。

JavaScript / TypeScript エディタ

コードを実行してください
QUIZ

理解度チェック

まずは1問ずつ答えてみましょう。

Q1const twice = n => n * 2; を宣言して twice(4) を表示すると、何が出ますか?

Q2const toItem = name => { label: name }; を呼び出したときの戻り値はどれですか?

Q3引数が 2 つのアロー関数で、引数を囲む丸括弧を省いて書くとどうなりますか?