1. JavaScriptの変数宣言とスコープ:var, let, this, undefinedの理解を深める
    1. JavaScriptの変数宣言「var」と「let」の違いを徹底解説
      1. 古き良き「var」の特性と潜在的リスク
      2. 現代の標準「let」がもたらす安心感
      3. varとletの比較と、もう一つの選択肢「const」
    2. JavaScriptの「this」の挙動とコンテキストの理解
      1. 「this」とは何か?そのコンテキスト依存性
      2. さまざまな呼び出しパターンと「this」の値
      3. 「this」の制御方法:call, apply, bindとアロー関数
    3. JavaScriptにおける「undefined」との向き合い方:判定方法とnullとの比較
      1. 「undefined」が発生する主なシナリオ
      2. 「undefined」の安全な判定方法と注意点
      3. 「undefined」と「null」の決定的な違い
    4. JavaScriptの条件分岐「if」と「switch」を使いこなす
      1. 「if」文の基本と柔軟な条件設定
      2. 「switch」文で複数の条件をスマートに処理
      3. 三項演算子とその他の条件分岐テクニック
    5. JavaScriptのループ処理と関数の基本:returnの役割
      1. さまざまなループ処理を理解する
      2. 関数の定義と呼び出しの基本
      3. 「return」文の重要性と役割
  2. まとめ
  3. よくある質問
    1. Q: JavaScriptの「var」と「let」の主な違いは何ですか?
    2. Q: JavaScriptの「this」は何を指しますか?
    3. Q: JavaScriptで変数が「undefined」かどうかを判定するにはどうすれば良いですか?
    4. Q: 「undefined」と「null」の違いは何ですか?
    5. Q: JavaScriptの「if」文で複数の条件を「OR」で指定するにはどうすれば良いですか?

JavaScriptの変数宣言とスコープ:var, let, this, undefinedの理解を深める

JavaScriptにおける変数宣言とスコープの理解は、効率的でバグの少ないコードを書く上で不可欠です。`var`、`let`、`this`、`undefined`といったキーワードは、その挙動を正確に把握する必要があります。

JavaScriptの変数宣言「var」と「let」の違いを徹底解説

古き良き「var」の特性と潜在的リスク

JavaScriptが誕生して以来、長く変数宣言の主役だったのが`var`キーワードです。しかし、その特性ゆえに開発者が意図しない挙動を引き起こす可能性があり、現代のJavaScript開発ではその使用が推奨されなくなっています。

`var`で宣言された変数は、関数スコープを持ちます。これは、変数が宣言された関数内であれば、どこからでもアクセス可能であることを意味します。たとえ`if`文や`for`ループのブロック(`{}`)内で宣言されても、そのブロックの外側から参照できてしまうため、大規模なコードベースでは変数の衝突や意図しない上書きのリスクが高まります。

さらに、`var`には巻き上げ(Hoisting)という特徴があります。これは、変数の宣言がそのスコープの先頭に物理的に移動したかのように振る舞う現象です。たとえば、変数を宣言する前に使用してもエラーにはならず、値が代入されるまではundefinedが返されます。これにより、コードのどこで変数が宣言されたのかを把握しにくくなり、デバッグが複雑になることがあります。また、`var`は同じスコープ内で再宣言再代入も可能なため、予期せぬ変数の上書きが発生するリスクも伴います。グローバルスコープで`var`を使うと、その変数はwindowオブジェクトのプロパティとして追加される点も、現代のモジュール化された開発においては望ましくない副作用となり得ます。

現代の標準「let」がもたらす安心感

ECMAScript 2015 (ES6) で導入された`let`キーワードは、`var`が抱えていた多くの問題を解決するために生まれました。現代のJavaScript開発において、変数を宣言する際の推奨事項となっています。

`let`の最大の特徴は、ブロックスコープを持つことです。これは、変数が宣言されたブロック(`{}`で囲まれた範囲)内でのみ有効であることを意味します。`if`文や`for`ループの中で`let`を使って宣言された変数は、そのブロックの外からはアクセスできず、ReferenceErrorが発生します。これにより、変数の有効範囲が明確になり、意図しない変数の衝突や上書きのリスクが大幅に減少します。これはコードの保守性と可読性を向上させる上で非常に重要な特性です。

`let`も宣言は巻き上げられますが、`var`とは異なり、宣言された箇所に到達するまで変数にアクセスできません。この期間は「一時的デッドゾーン(Temporal Dead Zone, TDZ)」と呼ばれ、アクセスしようとするとReferenceErrorが発生します。これにより、開発者は宣言前の変数アクセスという潜在的なバグを早期に発見できるようになります。また、`let`は同じスコープ内での再宣言は不可能ですが、値の再代入は可能です。これにより、変数の意図しない二重定義を防ぎつつ、必要に応じて値を更新できます。グローバルスコープで`let`を使っても、windowオブジェクトのプロパティにはならないため、グローバル汚染を防ぐことにも貢献します。(参考情報より)

varとletの比較と、もう一つの選択肢「const」

`var`と`let`の主な違いを理解することは、より堅牢なJavaScriptコードを書くための第一歩です。両者の特性を比較してみましょう。

特徴 var let const
スコープ 関数スコープ ブロックスコープ ブロックスコープ
巻き上げ される (undefinedで初期化) される (TDZ) される (TDZ)
再宣言 可能 不可 不可
再代入 可能 可能 不可 (参照型は中身変更可)
グローバルオブジェクトのプロパティ なる ならない ならない

(出典:参考情報に基づく比較)

現代のJavaScript開発では、`var`の使用は避けるべきだと強く推奨されています。代わりに、ブロックスコープを持つ`let`と`const`を状況に応じて使い分けるのがベストプラクティスです。

  • `const`:値が一度代入されたら、その後変更される必要がない定数には`const`を使用します。これにより、意図しない値の変更を防ぎ、コードの信頼性を高めることができます。ただし、オブジェクトや配列などの参照型の場合、変数が指す参照自体は変更できませんが、その中身(プロパティや要素)は変更可能です。
  • `let`:値が後から変更される可能性がある変数には`let`を使用します。ループカウンタや、ユーザー入力によって値が変わる変数などがこれに該当します。

このように`let`と`const`を適切に使い分けることで、変数の意図しない変更を防ぎ、コードの予測可能性と保守性を大幅に向上させることができます。

JavaScriptの「this」の挙動とコンテキストの理解

「this」とは何か?そのコンテキスト依存性

JavaScriptのthisキーワードは、他の多くの言語のそれに比べて非常にユニークで、多くの開発者を混乱させる要因の一つです。シンプルに言えば、thisは「現在実行されているコードのコンテキスト(文脈)」を参照します。しかし、この「コンテキスト」が何であるかは、関数がどのように呼び出されたかによって動的に決定されるため、その挙動を正確に理解することが不可欠です。(参考情報より)

グローバルスコープ(どの関数にも属さない一番外側の場所)でthisを使用した場合、ブラウザ環境では通常windowオブジェクトを指します。Node.js環境では、globalオブジェクトに近いオブジェクトを指しますが、モジュール内ではモジュールスコープのオブジェクトになります。この挙動は、JavaScriptの実行環境によって変化する典型的な例です。

`this`の値は、関数がオブジェクトのメソッドとして呼び出されたのか、通常の関数として呼び出されたのか、あるいはコンストラクタとして呼び出されたのかなど、「呼び出し方」によって大きく変わります。この柔軟性こそが`this`の強力な点であり、同時に複雑さの原因でもあります。`this`は変数ではないため、その値を直接変更することはできませんが、JavaScriptにはそのコンテキストを制御するためのさまざまなメカニズムが用意されています。(参考情報より)

さまざまな呼び出しパターンと「this」の値

thisの値を理解するには、具体的な呼び出しパターンごとにその挙動を見ていくのが最も効果的です。

  1. メソッド呼び出し: オブジェクトのプロパティとして定義された関数が、そのオブジェクトを介して呼び出される場合(例: obj.method())、thisそのオブジェクト自体を指します。

    const user = { name: 'Alice', greet() { console.log(`Hello, my name is ${this.name}`); } };

    user.greet(); // "Hello, my name is Alice"
  2. 関数呼び出し: オブジェクトのプロパティではなく、通常の関数として直接呼び出される場合(例: greet())、thisの挙動は環境とstrictモードの有無で異なります。

    • 非strictモード: thisグローバルオブジェクト(ブラウザでは`window`)を指します。
    • strictモード: thisundefinedを指します。

    function showThis() { console.log(this); }

    showThis(); // windowオブジェクト (非strictモード) または undefined (strictモード)

  3. コンストラクタ呼び出し: newキーワードを使って関数が呼び出される場合(例: new MyObject())、this新しく生成されたインスタンスを指します。

これらのパターンを把握することが、`this`を正しく扱うための基本となります。

「this」の制御方法:call, apply, bindとアロー関数

`this`の動的な性質は時に便利ですが、予測が難しい場合もあります。JavaScriptには、開発者が`this`のコンテキストを明示的に制御するための強力なメカニズムがいくつか用意されています。(参考情報より)

  • `call()` と `apply()` メソッド: これらのメソッドは、関数を特定の`this`コンテキストで直接実行するために使用されます。第一引数で`this`として使いたいオブジェクトを渡します。`call()`は残りの引数を個別に受け取りますが、`apply()`は引数を配列として受け取ります。

    function introduce(job, city) { console.log(`I am ${this.name}, a ${job} from ${city}.`); }

    const person = { name: 'Bob' };

    introduce.call(person, 'engineer', 'Tokyo'); // "I am Bob, a engineer from Tokyo."

    introduce.apply(person, ['designer', 'Osaka']); // "I am Bob, a designer from Osaka."
  • `bind()` メソッド: `bind()`は関数を直接実行するのではなく、`this`のコンテキストが固定された新しい関数を返します。これは、イベントハンドラなどで関数を渡す際に`this`のコンテキストを保持したい場合に特に便利です。

    const boundIntroduce = introduce.bind(person, 'artist');

    boundIntroduce('Kyoto'); // "I am Bob, a artist from Kyoto."
  • アロー関数: ES6で導入されたアロー関数は、独自のthisを持たず、定義されたスコープ(外側のスコープ)の`this`を継承します。これにより、`this`の挙動が予測しやすくなり、特にコールバック関数内で`this`を使う場合に非常に役立ちます。

これらのテクニックを使いこなすことで、複雑な`this`の問題を効果的に解決し、より堅牢なコードを書くことができます。

JavaScriptにおける「undefined」との向き合い方:判定方法とnullとの比較

「undefined」が発生する主なシナリオ

undefinedは、JavaScriptにおいて「値が割り当てられていない」状態を示すプリミティブな値です。これは、特定の状況下でシステムによって自動的に付与されるものであり、コードのデバッグやエラーハンドリングにおいてその発生原因を理解することが重要です。(参考情報より)

`undefined`が一般的に現れるシナリオは以下の通りです。

  1. 変数が宣言されたが、値が代入されていない場合:

    let myVar;

    console.log(myVar); // undefined

    これは最も典型的な`undefined`の発生源です。
  2. オブジェクトの存在しないプロパティにアクセスしようとした場合:

    const user = { name: 'Charlie' };

    console.log(user.age); // undefined

    オブジェクト`user`には`age`プロパティが存在しないため、`undefined`が返されます。
  3. 関数が明示的に値を返さない場合:

    function doSomething() { /* 何もreturnしない */ }

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

    JavaScriptの関数は、return文で明示的に値を返さない場合、暗黙的に`undefined`を返します。(参考情報より)
  4. 関数の引数が渡されなかった場合:

    function greet(name) { console.log(`Hello, ${name}`); }

    greet(); // Hello, undefined

    定義された引数に対応する値が呼び出し時に渡されない場合、その引数の値は`undefined`となります。

これらの状況を把握することで、コード内で`undefined`に遭遇した際に、何が原因で発生したのかを素早く特定できるようになります。

「undefined」の安全な判定方法と注意点

コード内で`undefined`であるかどうかを正確に判定することは、エラーを防ぎ、堅牢なアプリケーションを構築するために非常に重要です。いくつかの判定方法がありますが、それぞれに注意点があります。

最も安全で推奨される方法は、厳密等価演算子 (===) を使用することです。

let value; // valueはundefined

if (value === undefined) { console.log("value is strictly undefined"); } // このブロックが実行される

この方法は、型と値の両方を比較するため、予期せぬ型変換による誤判定を防ぎます。

もう一つの一般的な方法は、`typeof`演算子を使用することです。

let value;

if (typeof value === 'undefined') { console.log("value's type is undefined"); } // このブロックが実行される

`typeof`はオペランドの型を表す文字列を返すため、'undefined'という文字列と比較します。これは、未宣言の変数に対してもエラーなく機能するという利点があります。

一方で、緩い等価演算子 (==) で`undefined`を判定することは避けるべきです。

let value = null;

if (value == undefined) { console.log("value is loosely undefined"); } // このブロックも実行される (null == undefined は true)

`==`は型変換を行うため、nullも`undefined`と等価とみなしてしまいます。また、真偽値への変換(例: `if (!value)`)も、`undefined`だけでなく`null`, `0`, `””`, `false`などもFalsy値として扱うため、特定の状況では意図しない結果を招く可能性があります。特定の「値がない」状態だけをチェックしたい場合は、厳密等価演算子か`typeof`を使用しましょう。

「undefined」と「null」の決定的な違い

JavaScriptには、「値がない」ことを示す二つのプリミティブ値、undefinednullが存在します。これらは似ているようで、その意味合いと使われ方には決定的な違いがあります。この違いを理解することは、コードの意図を明確にし、潜在的なバグを防ぐ上で非常に重要です。

  • `undefined`: 「値が割り当てられていない」状態をシステムが示すものです。これは主に、変数が宣言されたが初期化されていない、オブジェクトの存在しないプロパティにアクセスした、関数が何も返さなかった、といった場合に発生します。(参考情報より) 開発者が明示的に変数に`undefined`を代入することは稀であり、通常はJavaScriptエンジンによって自動的に付与される値です。
  • `null`: 「意図的に値が存在しない」ことを示すために、開発者が明示的に代入する値です。これは、「オブジェクトを指すべき変数が、現時点ではどのオブジェクトも指していない」という状態を表すためによく使用されます。例えば、データベースからユーザーが見つからなかった場合や、要素がDOMに存在しない場合などに`null`を返したり代入したりします。(参考情報より)

両者の`typeof`演算子の結果も異なります。

  • `typeof undefined` は "undefined" を返します。
  • `typeof null` は、歴史的な理由により "object" を返します。(参考情報より) これはJavaScriptの設計上の有名な「バグ」の一つとされています。

要するに、`undefined`は「まだ値がない」、`null`は「意図的に値がない」と区別できます。どちらも`Falsy`値であるため、条件分岐で`if (!value)`とすると両方を同じように扱ってしまいますが、特定の状態をチェックしたい場合は、`===`で厳密に比較することが推奨されます。例えば、ユーザーがログインしていない状態を`null`で表し、まだユーザー情報を取得していない状態を`undefined`で表す、といった使い分けが可能です。

JavaScriptの条件分岐「if」と「switch」を使いこなす

「if」文の基本と柔軟な条件設定

JavaScriptにおける条件分岐の最も基本的な構造がifです。特定の条件が真(true)である場合にのみコードブロックを実行し、プログラムの流れを制御します。そのシンプルさから、あらゆるプログラミングにおいて不可欠な要素となっています。

基本的な構文は以下の通りです。

if (条件式) { /* 条件式が真の場合に実行されるコード */ }

else if (別の条件式) { /* 最初の条件式が偽で、別の条件式が真の場合に実行されるコード */ }

else { /* 全ての条件式が偽の場合に実行されるコード */ }

`else if`や`else`はオプションであり、条件に応じて複数の分岐を作成できます。`if`文の「条件式」には、真偽値(`true`または`false`)を返す式が入ります。JavaScriptでは、真偽値に変換すると`true`になる値をTruthy(例: 非空文字列、0以外の数値、オブジェクト)、`false`になる値をFalsy(例: `0`, `””`, `null`, `undefined`, `false`)と呼び、これらは`if`文の条件として直接使用できます。

複数の条件を組み合わせるには、論理演算子が活用されます。

  • && (AND): 両方の条件が真の場合に真。
  • || (OR): いずれかの条件が真の場合に真。
  • ! (NOT): 条件の真偽値を反転。

例えば、ユーザーがログインしており、かつ管理者権限を持っている場合にのみ特定の操作を許可する、といった複雑な条件も`if`文と論理演算子を組み合わせることで実現できます。その柔軟性から、`if`文はあらゆる状況で幅広く利用されます。

「switch」文で複数の条件をスマートに処理

複数の選択肢の中から特定の値を基準に処理を分岐させたい場合、switchが非常に役立ちます。特に、一つの変数の値に基づいて異なる処理を行う場合に、if-else ifの長い連鎖よりもコードを簡潔かつ読みやすくすることができます。

`switch`文の基本的な構文は以下の通りです。

switch (式) {

  case 値1:

    // 式が値1と一致した場合の処理

    break;

  case 値2:

    // 式が値2と一致した場合の処理

    break;

  default:

    // どのcaseにも一致しなかった場合の処理 (オプション)

    break;

}

`switch`文は、指定された`式`の値と、各`case`の`値`を厳密等価演算子 (===)で比較します。一致する`case`が見つかると、その`case`ブロック内のコードが実行されます。

ここで重要なのがbreakです。breakがないと、一致した`case`以下の全ての`case`ブロック(`default`を含む)が実行されてしまいます。これを「フォールスルー(fall-through)」と呼び、意図しない挙動につながることが多いため、各`case`の最後に`break`を記述するのが一般的です。`default`ブロックは、どの`case`にも一致しなかった場合に実行される処理を定義するために使用され、オプションですが、予期せぬ入力への対応として設定することが推奨されます。

例えば、HTTPステータスコードに応じて異なるメッセージを表示する、ユーザーが選択したメニュー項目に応じて特定の関数を実行するなど、特定の「値」に基づいて処理を振り分けたい場合に`switch`文は強力なツールとなります。複数の条件を簡潔に、そして明確に表現する能力は、コードの可読性を大きく向上させます。

三項演算子とその他の条件分岐テクニック

`if`文や`switch`文が複雑な条件分岐に優れる一方で、JavaScriptにはより簡潔な記述を可能にする条件分岐テクニックも存在します。これらを適切に使いこなすことで、コードの可読性と効率性をさらに高めることができます。

  1. 三項演算子 (Conditional Ternary Operator):

    これは、シンプルな条件に基づいて値を代入したり、短い式の結果を返す場合に非常に便利です。

    const age = 18;

    const message = (age >= 18) ? "Adult" : "Minor";

    console.log(message); // "Adult"

    構文は条件式 ? 式1 : 式2で、`条件式`が真なら`式1`が、偽なら`式2`が実行されます。特に変数の初期化やJSX/TSX内での条件付きレンダリングなどで頻繁に利用されます。ただし、複雑なロジックを三項演算子で記述すると可読性が低下するため、シンプルな場合に限定して使用することが推奨されます。
  2. 論理AND (&&) 演算子によるショートサーキット評価:

    左辺がTruthyであれば右辺の評価を行い、その結果を返します。左辺がFalsyであれば、右辺は評価されずに左辺の値を返します。

    const isLoggedIn = true;

    isLoggedIn && console.log("ユーザーはログインしています。"); // ログインしていれば表示

    これは、特定の条件が満たされた場合にのみ処理を実行したい、というシナリオで`if`文の代わりに簡潔に記述できます。
  3. 論理OR (||) 演算子によるショートサーキット評価:

    左辺がTruthyであれば左辺の値を返し、右辺は評価されません。左辺がFalsyであれば右辺の評価を行い、その結果を返します。

    const userName = null;

    const displayName = userName || "ゲスト";

    console.log(displayName); // "ゲスト" (userNameがFalsyなので)

    これは、デフォルト値を設定する際によく用いられます。
  4. Nullish Coalescing (??) 演算子 (ES2020以降):

    `||`と似ていますが、左辺がnullまたはundefinedの場合にのみ右辺の値を返します。`0`や空文字列(`””`)のようなFalsy値は`null`や`undefined`とは見なされないため、より厳密なデフォルト値の設定が可能です。

    const count = 0;

    const displayCount = count ?? 100;

    console.log(displayCount); // 0 (countはnull/undefinedではないため)

これらのテクニックを組み合わせることで、JavaScriptの条件分岐はより表現豊かで効率的なものになります。状況に応じて最適な方法を選択することが、優れたコードを書く鍵となります。

JavaScriptのループ処理と関数の基本:returnの役割

さまざまなループ処理を理解する

JavaScriptにおけるループ処理は、配列の要素を一つずつ処理したり、特定の条件が満たされるまで繰り返し処理を実行したりする際に不可欠です。用途に応じて様々な種類のループ構文が用意されており、それぞれの特性を理解して適切に使い分けることが重要です。

  1. forループ: 最も基本的なループで、初期化、条件、更新の3つの式で制御されます。主に配列のインデックスに基づく反復処理や、回数が決まっている処理に適しています。

    for (let i = 0; i < 3; i++) { console.log(i); } // 0, 1, 2
  2. whileループ: 指定した条件式が真である間、処理を繰り返し実行します。回数が不明確で、ある条件が満たされるまで続けたい場合に有効です。無限ループにならないよう、条件を変更する処理を必ず含める必要があります。

    let count = 0;

    while (count < 3) { console.log(count); count++; } // 0, 1, 2
  3. for...ofループ (ES6以降): 配列や文字列、Set、Mapなどのイテラブルオブジェクトの要素のを直接取得して反復処理を行う場合に最適です。シンプルで可読性が高いのが特徴です。

    const colors = ['red', 'green', 'blue'];

    for (const color of colors) { console.log(color); } // red, green, blue
  4. forEach()メソッド: 配列に特化した高階関数で、配列の各要素に対して指定されたコールバック関数を実行します。インデックスも取得できますが、`break`や`continue`でループを中断することはできません。

    const numbers = [1, 2, 3];

    numbers.forEach(num => console.log(num)); // 1, 2, 3

その他にも、オブジェクトのプロパティを列挙するためのfor...inループがありますが、これは継承されたプロパティも列挙してしまう可能性があり、通常はオブジェクトのプロパティを反復処理するにはObject.keys()Object.entries()などのメソッドが推奨されます。目的に応じて最適なループ処理を選択することが、効率的で分かりやすいコードにつながります。

関数の定義と呼び出しの基本

JavaScriptにおける関数は、特定のタスクを実行するためのコードのブロックであり、プログラムの再利用性、モジュール性、保守性を高める上で非常に重要な役割を果たします。関数を定義し、それを呼び出すことで、同じ処理を何度も書く手間を省くことができます。

関数の定義方法はいくつかあります。

  1. 関数宣言 (Function Declaration): 最も伝統的な方法で、名前付き関数を定義します。巻き上げ(hoisting)の対象となるため、定義より前に呼び出すことができます。

    function sayHello(name) { console.log(`Hello, ${name}!`); }

    sayHello('Alice'); // "Hello, Alice!"
  2. 関数式 (Function Expression): 関数を値として変数に代入する方法です。巻き上げはされず、変数に代入されてから呼び出す必要があります。無名関数(名前を持たない関数)として定義されることが多いです。

    const greet = function(name) { console.log(`Greetings, ${name}!`); };

    greet('Bob'); // "Greetings, Bob!"
  3. アロー関数 (Arrow Function) (ES6以降): 関数式をより簡潔に記述できる構文です。特に、コールバック関数として使用される場面でその威力を発揮します。アロー関数は独自のthisを持たず、外側のスコープの`this`を継承するという特徴があります。

    const multiply = (a, b) => a * b;

    console.log(multiply(2, 3)); // 6

関数には引数を渡すことができ、関数内でその引数を利用して処理を行います。関数はまた、戻り値を返すことができ、これは`return`文によって制御されます。適切に関数を定義し、モジュール化することで、大規模なアプリケーションも管理しやすくなります。

「return」文の重要性と役割

returnは、JavaScriptの関数において非常に重要な役割を担っています。その主な機能は二つあります。

  1. 関数の実行を終了し、呼び出し元に制御を戻す:

    `return`文が実行されると、その時点で関数の残りのコードは実行されずに終了し、関数の呼び出し元に制御が移ります。これは、特定の条件が満たされた場合に早期に関数を終了させる「早期リターン」のパターンで特に有用です。

    function checkAge(age) {

      if (age < 0) {

        console.log("無効な年齢です。");

        return; // ここで関数が終了

      }

      console.log(`あなたの年齢は${age}歳です。`);

    }

    checkAge(-5); // "無効な年齢です。"が表示され、それ以下は実行されない
  2. 関数の結果として値を返す:

    `return`文の後ろに値を記述することで、その値を関数の呼び出し元に渡すことができます。これにより、関数が計算結果や処理の結果を他の部分で利用できるようになります。

    function add(a, b) { return a + b; } // aとbの合計値を返す

    const result = add(5, 10);

    console.log(result); // 15

`return`文が省略された関数、あるいは`return;`のように何も指定せずに`return`が実行された関数は、暗黙的にundefinedを返します。(参考情報より) これは、関数が副作用(画面に何かを表示するなど)のみを行い、特定の計算結果を必要としない場合に一般的です。

複数の`return`文を条件分岐(`if/else`など)と組み合わせて使用することで、異なる条件に基づいて異なる値を返したり、早期にエラー状態を処理したりすることが可能になります。`return`を効果的に活用することは、関数の役割を明確にし、コードの可読性と予測可能性を高めるために不可欠なスキルです。