複数の戻り値パターン

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

複数の戻り値パターン とは

関数からまとめて複数の値を返したいときは、オブジェクトに詰めて返そう。本レッスンでは、複数の戻り値パターン の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

1 つの関数で複数の値を返したい

関数を書いていると「return で 2 つ以上の値を返したい」というシーンが必ず出てきます。たとえば「最小値と最大値を両方返す」「商と余りを両方返す」「ユーザー情報をまとめて返す」など、関連する値はセットで欲しいものです。

ところが JavaScriptreturn 文は 1 つの値しか返せません。これは JavaPython でも同じです。じゃあどうするのかというと、1 つの「箱」にまとめて返す という発想で解決します。JavaScript でその箱の代表が オブジェクト です。

JavaScript

function divmod(a, b) { return { quotient: Math.floor(a / b), remainder: a % b }; } const result = divmod(17, 5); console.log(result.quotient); // => 3 console.log(result.remainder); // => 2

{ quotient: ..., remainder: ... } がオブジェクトです。{} で囲んで、キー: 値 のペアをカンマで区切って並べると、関連する値を 1 つの箱にまとめられます。

オブジェクトは JavaScript の心臓部です。配列もオブジェクトの一種、関数もオブジェクトの一種。「とにかく {} で何でも表現する」のが JavaScript の世界観だと覚えておきましょう。

オブジェクトの基本形

オブジェクトの作り方をもう少し見てみます。

JavaScript

const user = { name: "Alice", age: 28, isAdmin: false, }; console.log(user.name); // => Alice console.log(user["age"]); // => 28 console.log(user.isAdmin); // => false

値を取り出すときは user.name のようにドット . で書くか、user["name"] のように角カッコ [] で書きます。動的にキーを決めたいときだけ []、それ以外はドット . を使うのが一般的です。

オブジェクトのキーは「フィールド」「プロパティ」「メンバー」など色々な呼び方をされますが、どれも同じものを指しています。最初は「キー」と覚えておけば十分です。

配列との使い分け

複数の値をまとめる入れ物には、もう 1 つ 配列 もあります。

JavaScript

function minMax(numbers) { return [Math.min(...numbers), Math.max(...numbers)]; } const [min, max] = minMax([3, 1, 4, 1, 5]); console.log(min, max); // => 1 5

配列は [] で囲み、順番に並べた値だけを持ちます。「最小、最大」のように 順序が明確 な 2 値ならスマートですが、[28, false, "Alice"] のように意味の違う値を並べると、後で「何番目が何だったっけ?」となりがちです。

そのため、3 つ以上の値や意味が違う値はオブジェクト、対称的な 2 値は配列、というのが目安になります。

返し方の流れを図で見る

オブジェクトで返す流れを、図で確認しておきましょう。

diagram (will load when visible)

計算した複数の値をいったん {} に詰めて、return で渡し、呼び出し側で .キー名 で必要な値を取り出す、という流れになります。

分割代入で受け取る

オブジェクトで返ってきた値は、分割代入 という構文ですっきり取り出せます。

JavaScript

function profile(name, age) { return { displayName: name, ageLabel: age + " 歳" }; } const { displayName, ageLabel } = profile("Alice", 28); console.log(displayName); // => Alice console.log(ageLabel); // => 28 歳

const { displayName, ageLabel } = ... という書き方で、オブジェクトのキーと同じ名前の変数に一気に代入できます。これも第 7 章でじっくり学ぶので、今は「便利な書き方があるんだな」程度で OK です。

オブジェクトを返す関数はテストもしやすくなります。「複数の戻り値を 1 つの構造として比較できる」からです。同じ理由で、React のフックなども多くがオブジェクトを返す形になっています。

よくある間違い

オブジェクト返しでよくある落とし穴を 3 つ紹介します。

  • return{ の間で改行するJavaScript の ASI のせいで、return のすぐ後ろで改行すると return; と解釈されて undefined が返ります。return { は同じ行に書くのが鉄則です
  • キーの引用符を間違える — オブジェクトリテラルのキーは引用符なしで書けますが、name-with-dash のようなハイフンを含む名前はクォートが必要です。普段は引用符なしで十分です
  • キー名のタイポresult.quantity と書きたいのに result.qantity と書くと、エラーにならず undefined が返ります。型チェックがない世界では、タイポを発見しづらいので注意が必要です

オブジェクトを返す関数は「API のレスポンス」と思うとイメージしやすいです。クライアントは決まったキー名で値を取り出すので、キー名を変えると影響範囲が大きくなります。

やってみよう

それでは課題に挑戦しましょう。divmod という関数を作って、余り をオブジェクトにまとめて返します。

  1. 引数 ab を受け取る
  2. Math.floor(a / b) で商を計算 (整数の商)
  3. a % b で余りを計算
  4. { quotient: 商, remainder: 余り } の形で return する

divmod(17, 5){ quotient: 3, remainder: 2 }divmod(10, 3){ quotient: 3, remainder: 1 } を返します。テストはオブジェクトの中身まで比較するので、キー名 (quotientremainder) を正確に書いてください。

慣れてきたら、{ q: 3, r: 2 } のように短いキー名にしたり、配列 [3, 2] で返したりして、書き換えごとに「何が便利で何が不便か」を体感してみてください。

よくある質問

Q. ブラウザと Node.js で動作は変わりますか?

A. JavaScript の構文・組み込み機能(配列・文字列・Promise 等)はどちらでも同じです。違いは DOM API(ブラウザ専用)と fs などのファイル系(Node 専用)など、実行環境固有の機能です。コアロジックは両方で動くため、テストもしやすくなります。

Q. ES6 以降の新機能は使っても大丈夫ですか?

A. 現代のブラウザ・Node.js は ES2020 以降の機能をほぼサポートしています。古い IE 等を対象にする必要が無ければ、let/const、アロー関数、分割代入、async/await を積極的に使ってください。トランスパイル(Babel/Vite)が必要なケースは年々減っています。

Q. TypeScript に進む価値はありますか?

A. 型情報があるとリファクタやエディタ補完が劇的に効くため、規模が大きくなるなら TypeScript への移行を強くおすすめします。最初は any を許容しつつ徐々に型を付ければ、JS の知識をそのまま活かせます。

次のレッスン

次は JS が動く順番を意識する で、関数からまとめて複数の値を返したいときは、オブジェクトに詰めて返そう を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. オブジェクトで返す の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. オブジェクトで返す とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. 関数名は divmod、引数は ab の 2 つ
  2. 戻り値は { quotient: 商, remainder: 余り } 形式のオブジェクト
  3. 商は Math.floor(a / b)、余りは a % b で計算すること

入出力例

test-cases.txt

divmod(17, 5){"quotient":3,"remainder":2} divmod(10, 3){"quotient":3,"remainder":1} divmod(20, 4){"quotient":5,"remainder":0} divmod(0, 7){"quotient":0,"remainder":0}

ヒント

main.js
main.js
学習モード

メモ

複数の戻り値パターン

⌘S で保存