【JavaScript】returnとは?値の返し方や実践的な使い方を初心者向けにわかりやすく解説

はじめに

JavaScriptでプログラミングをするとき、関数の中でよく見かけるのが return です。
この return は単なる「結果を返すもの」だと理解されがちですが、実は初心者がつまずきやすいポイントが多く含まれています。
たとえば「関数の途中で処理を終わらせたい」「配列やオブジェクトをまとめて返したい」「非同期処理の中でreturnはどう動くのか」など、いざ実務や学習の段階に入ると多くの疑問が出てくるでしょう。
そこでこの記事では、JavaScriptでの return の基本的な仕組みから、具体的な活用方法までをわかりやすく解説していきます。
初心者の方でも安心して読み進められるよう、専門用語は可能な限り噛み砕いて説明しますので、ぜひ最後までご覧ください。

この記事を読むとわかること

  • return が果たす基本的な役割と書き方
  • 関数の途中でreturnを使うことで得られるメリット
  • 配列やオブジェクトを返す場合の具体的な方法
  • アロー関数におけるreturnの書き方の違い
  • 実務で役立つreturnの活用シーンや注意点

JavaScriptでのreturnとは?

JavaScriptにおける return は、関数が「何を結果として返すのか」を指定するための命令です。
同時に、「関数の処理をそこで終了させる」という重要な役割も担っています。
この仕組みをしっかり理解しないままプログラミングを進めると、いつの間にか想定外の値が返ってしまい、バグに悩まされることもあります。

JavaScript関数におけるreturnの基本

JavaScriptでは、function キーワードやアロー関数を用いて関数を定義できますが、いずれの場合も return は「関数が外部に返す結果」を明示的に指定するために使われます。
以下のようなコードを見てみましょう。

function addNumbers(a, b) {
  const sum = a + b;
  return sum;
}

この場合、関数 addNumbers が呼び出されると、最後の行にある return sum; によって計算結果が呼び出し元に返されます。
たとえば console.log(addNumbers(3, 5)); と実行すると 8 が出力されるわけです。
また、return が実行された時点で、その関数の処理は終了します。

returnで値を返す方法

上記の例では変数 sum を返しましたが、直接数値や文字列を返すことも可能です。
たとえば return a + b; のように式をそのまま return に書いてしまうことも多いです。
このように、値そのもの、あるいは式の計算結果を return することで、呼び出し元へ必要なデータを渡せます。
文字列なら return "Hello"; のように書きますし、ブーリアン値(true / false)やオブジェクト、配列もそのまま返せます。

returnの動作例

次のコードは、2つの値を加算して返す関数と、文字列を返す関数の例です。

function add(a, b) {
  return a + b;
}

function sayHello(name) {
  return "Hello, " + name + "!";
}

console.log(add(10, 2));       // 12
console.log(sayHello("Tom")); // Hello, Tom!

このように、return で返した値が呼び出し側で使えるようになるのが基本的な仕組みです。

returnを使わない場合との違い

もし return を書かずに関数の処理を終わらせると、その関数は undefined を返します。
これは「明示的に値が指定されていない」という状態を意味します。
たとえば次のような関数は、実行しても何も返しません。

function doNothing() {
  const x = 100;
  // return文なし
}

console.log(doNothing()); // undefined

こういったケースでは、呼び出し元に値を渡すつもりがないのか、それとも書き忘れなのかを明確にしておくことが大切です。

returnが持つ重要な役割

1つ目は「計算結果や処理結果など、外部に渡したいデータを返す」こと。
2つ目は「関数内の処理を早期に終了させる」ことです。
単に値を返すだけでなく、特定の条件を満たした場合に処理を打ち切ることによって、コードの可読性やパフォーマンスを向上させることができます。
この「途中で処理を打ち切る」使い方は後述する「早期return」で詳しく説明します。

returnの活用パターン

ここでは、実務でよく使われるreturnの具体的なパターンをいくつか取り上げます。
単純な「計算結果を返す」という使い方から一歩進んで、条件分岐やループ内で活用する方法を見ていきましょう。

if文による条件分岐とreturn

returnはif文と組み合わせて条件を満たしたらそこで処理を終了させる、といった使い方が多いです。

function checkAge(age) {
  if (age < 20) {
    return "未成年です";
  }
  return "成人です";
}

この関数は、引数 age が 20未満なら "未成年です" を返して処理を終了します。
もし age >= 20 の場合は、ifの内部が実行されないため、関数の最後の行に書かれている return が実行され、"成人です" を返します。

早期returnの活用

「早期return」とは、複数の条件判定やエラー処理がある場合に、要件を満たしていないときは即座にreturnしてしまうテクニックです。
これによって関数のネストが深くなるのを防ぎ、コードを読みやすくできます。

function processData(data) {
  // データがnullまたはundefinedなら処理しない
  if (!data) {
    return "データがありません";
  }
  
  // データが正しい型でなければ処理しない
  if (typeof data !== "object") {
    return "オブジェクト形式のデータではありません";
  }

  // 実際の処理
  // ...なんらかのロジック
  return "データを処理しました";
}

このように、要件を満たさないケースを先に弾いてreturnし、後続の処理を実行しない構造にしておくと可読性が高まります。

switch文やループ内での使い方

switch文やループの中でreturnを使うと、その時点で関数全体の処理が終了します。
たとえば次のようなスニペットを見てみましょう。

function findFirstEven(numbers) {
  for (let i = 0; i < numbers.length; i++) {
    if (numbers[i] % 2 === 0) {
      return numbers[i];
    }
  }
  return null; // 偶数が見つからなかった場合
}

リストの中から最初に見つかった偶数を返した時点で関数が終わるため、無駄なループを続ける必要がなくなります。
switch文も同様の原理で、該当のケースを見つけたらreturnして関数を終わらせるという実装が可能です。

複数の値を返す方法

JavaScriptの関数は、一度のreturnで「1つの値」しか返せません。
しかし、実際の開発では「複数のデータをまとめて返したい」という状況がよく起こります。
ここでは、オブジェクトや配列を使って複数の値を返す方法を紹介します。

オブジェクトを返す例

オブジェクトを返すときは、複数のプロパティをまとめて返せるのがメリットです。

function createUserProfile(name, age) {
  return {
    name: name,
    age: age,
    isAdult: age >= 20
  };
}

const profile = createUserProfile("Alice", 25);
console.log(profile.name);   // Alice
console.log(profile.age);    // 25
console.log(profile.isAdult); // true

オブジェクトのプロパティを増やせば、さまざまな情報をまとめて返すことができます。
これにより、管理もしやすくなりますし、呼び出す側もデータを取り出しやすいでしょう。

配列を返す例

もし返すデータに「順序」が重視される場合や、「同じ型の要素」が連続して並ぶ場合には、配列を返した方が扱いやすいかもしれません。

function getRange(start, end) {
  const result = [];
  for (let i = start; i <= end; i++) {
    result.push(i);
  }
  return result;
}

const rangeArray = getRange(1, 5);
console.log(rangeArray); // [1, 2, 3, 4, 5]

ここではシンプルに連番を並べただけですが、大量のデータをまとめて返すときにも配列は有力な選択肢です。

破壊的な返り値を避けるための注意点

オブジェクトや配列を返す場合、受け取る側がその返ってきた配列やオブジェクトを直接変更すると、あとから不具合が生じることもあります。
むやみにデータを変更されないようにしたい場合は、スプレッド構文や別の手法を用いて「コピー」を返すことを検討してみてください。

function getDataObject(originalData) {
  // オブジェクトのコピーを返す例
  return { ...originalData };
}

このようにすると、呼び出し元が返されたオブジェクトを変更しても、元の originalData に影響を及ぼさないようにできます。

アロー関数とreturn

アロー関数でも基本的な原則は同じですが、構文による微妙な違いが存在します。
とくに 即時return 可能なケースと、ブロック構文を使うケースでは書き方が変わるため注意が必要です。

即時returnと省略可能なポイント

アロー関数では、関数本体が1行で終わる単純な式の場合に限り、return キーワードを省略できます。

const double = x => x * 2;

この1行だけで、引数 x に対して x * 2 が返される仕組みです。
もし複数の処理がある場合は {} でブロックを定義し、その中に return を書く必要が出てきます。

を使ったブロック構文との違い

以下の2つの例を比較してみてください。

// 即時returnするケース
const greet = name => "Hello, " + name;

// ブロック構文を使うケース
const greetWithBlock = name => {
  return "Hello, " + name;
};

上の行は1行で結果を返すので return が省略されており、下の行はブロック構文を使用しているため return が必要となります。
初心者の方は、この辺りの違いに戸惑うことが多いため、まずはシンプルな構文から慣れていくのがおすすめです。

returnが動作しないケースに注意

JavaScriptで関数を作るとき、間違った書き方や非同期処理の仕組みを誤解していると、意図したとおりに return が働かないケースがあります。
ここでは代表的な例を紹介します。

コールバック関数内でのreturn

コールバック関数の中で return しても、外側の関数には影響しないことが多いです。
たとえば非同期の処理中にコールバックでreturnしても、それは「コールバック関数自体のreturn」であって、外側の関数が値を返すわけではありません。

function asyncExample() {
  setTimeout(() => {
    return "完了"; 
  }, 1000);
}

const result = asyncExample();
console.log(result); // ここは undefined になる

このコードでは、setTimeout のコールバック内部で return しても、asyncExample() 関数全体が返す値にはならないのです。
非同期関数やPromiseを扱う場合も、return のタイミングに注意しないと想定外の結果を招きます。

非同期処理との組み合わせ

非同期処理を行う場合は、基本的に return ではなく コールバックPromiseasync/await などを活用しながら値を取得します。
以下はasync/awaitを使った例です。

async function fetchData() {
  // fetchの結果をawaitし、そのままreturnで返す
  const response = await fetch("https://example.com/data");
  const jsonData = await response.json();
  return jsonData;
}

async function main() {
  const data = await fetchData();
  console.log(data);
}

main();

このように、async 関数では return で返した値が Promise オブジェクトとして扱われます。
非同期処理を正しく理解していないと、returnの値がタイミング通りに返らず困惑することがありますので注意してください。

returnを使うときの注意点

returnを正しく使うことでコードが分かりやすくなりますが、いくつかの注意点も存在します。
ここでは典型的なトラブルや可読性に関するポイントを見ていきましょう。

関数の途中でreturnする場合の注意

早期returnが便利だからといって、あまりに多用すると関数全体の構造が把握しづらくなることもあります。
条件分岐が多い場合は、まず「なぜそんなに条件が発生するのか」を見直し、ロジックを整理してみることも大切です。
また、returnするタイミングや条件が増えすぎると、どのルートで関数が終了するのか追いにくくなります。
見落としによってバグにつながらないように気をつけましょう。

コードの読みやすさと保守性

returnの位置や数が多いと、保守する人が混乱する可能性があります。
とくにチーム開発では、別のエンジニアがコードを読むときのことを想定し、どのような条件でreturnされるのか明確にしておくと安心です。
たとえば条件分岐が多い場合は、コメントを挟んだり、関数を細分化したりして見通しを良くすると良いでしょう。

複数のreturn文がある関数は、読み手によっては理解しづらい場合があります。 条件ごとに処理を分割したり、補助的な関数に切り出したりしてみると、全体の可読性が高まります。

実務でのreturn利用シーン

returnは学習段階だけでなく、実務の様々な場面でも利用されます。
特に以下のようなシーンでは活躍の場が広がり、正しい使い方を理解していると効率的に開発を進めることができます。

APIレスポンスの整形

Webアプリケーション開発では、外部のAPIから取得したデータを加工して、フロントエンドに返すことがよくあります。
サーバーサイドの関数内でデータをまとめて return し、呼び出し元がそれを利用するイメージです。
たとえばNode.jsなどでREST APIを作る際、取得したJSONをある程度整形してからreturnし、それをクライアントに送信する、という流れが典型的です。

フロントエンド開発でのUI描画

フロントエンド開発でも、コンポーネントや画面ごとのロジック内で、関数を使ってデータを加工してからreturnする場面が多いでしょう。
ロジックを部分的に関数化することで、コードが分割しやすくなりますし、テストも行いやすくなります。
returnで正しく値を返すことで、UIに意図した表示を実現できます。

ライブラリ開発における関数設計

ライブラリやフレームワークを作る場合、関数の返り値をどう設計するかは非常に重要です。
ユーザーが関数を呼び出したとき、何が返ってくると使いやすいか を考えることで、ライブラリ全体の使い勝手が大きく変わります。
複数の型を返すようにするか、あるいはエラー時にエラーメッセージやステータスコードを含むオブジェクトを返すかなど、設計上の判断が必須です。

returnのトラブルシューティング

ここまでの説明でreturnの基本と実務上のポイントが分かってきたと思いますが、それでも特定のトラブルに遭遇することはよくあります。
ここからは、初心者がよく陥るトラブルとその対処法を見ていきましょう。

undefinedが返ってしまう原因

「期待した値が返ってこない。
結果をログで確認してみたら、undefined だった」という状況は非常に多いです。
この主な原因としては、return文自体を忘れている か、非同期処理の結果がまだ得られていない かの2つが考えられます。

1. return文が書かれていない

関数の最後にreturnを記述していない、あるいは条件分岐の中だけに書いていて他の分岐ではreturnしていないなどのケースです。

2. 非同期処理の結果が遅れて届く

先に紹介したように、非同期の世界ではreturnしても関数を呼び出した直後に値を取得できないケースがあります。

このあたりを意識していないと、「なんでreturnが効かないんだろう?」と混乱してしまうでしょう。

returnの書き忘れ

実務でよくあるのが「計算結果を変数に代入したけれど、最後にreturnしていなかった」という単純なミスです。
以下の例は、処理自体は行っているのに、結果を返していません。

function multiply(a, b) {
  const product = a * b;
  // return product; が抜けている
}

この場合、呼び出し元で multiply(2,3) を実行しても、返ってくるのは undefined になります。
ちょっとした勘違いでやりがちなエラーなので、意識してチェックしましょう。

return文とセミコロン自動挿入

JavaScriptではセミコロンの自動挿入(ASI: Automatic Semicolon Insertion)という仕様があり、return の直後に改行を入れてしまうと意図しない動作を起こすことがあります。

function example() {
  return
    {
      message: "Hello"
    };
}

実はここ、JavaScriptエンジンが return の後ろにセミコロンを自動的に挿入するため、return; とみなされます。
結果として { message: "Hello" } は無視され、undefined が返されてしまうのです。
もしオブジェクトを返すなら、以下のように同じ行に書くか、丸括弧を使うなどの対策をとりましょう。

function example() {
  return {
    message: "Hello"
  };
}

セミコロンの自動挿入は思わぬバグを引き起こすことがあります。 特にreturnの直後は改行しないように注意してください。

まとめ

この記事では、JavaScriptの return について基本的な概念から実務的な活用方法まで、様々な側面を解説しました。
一言で「関数の返り値を指定するもの」と言ってしまうとシンプルですが、実際には以下のようなポイントを意識する必要があります。

  • 関数の処理を途中で終了させる役割
  • if文やswitch文などの条件分岐と合わせた使い方
  • 複数の値を返したい場合のオブジェクトや配列の活用
  • アロー関数でのreturnの省略やブロック構文との違い
  • 非同期処理ではreturnがそのまま結果にならないケースがある

初めはreturnを単純に値を返すものだと捉えがちですが、実際にコードを書いてテストしてみると、いろいろな落とし穴や便利な使い方を発見できるでしょう。
特に実務では、returnをどこで行うかがコードの構造やパフォーマンスに直結します。
早期returnでネストを浅くしたり、オブジェクトを返してデータ管理を簡単にしたり、非同期処理ではPromiseを組み合わせたりすることで、効率的な開発が可能です。

皆さんもこの機会にreturnの動きをしっかり理解し、書いたコードを実行しながら試してみてください。
そうすることで、JavaScriptの関数設計がよりスムーズに進むようになるはずです。
使い方を押さえてしまえば、returnは非常にシンプルかつ強力なツールになりますので、ぜひ活用してみてください。

JavaScriptをマスターしよう

この記事で学んだJavaScriptの知識をさらに伸ばしませんか?
Udemyには、現場ですぐ使えるスキルを身につけられる実践的な講座が揃っています。