【JavaScript】デフォルト引数とは?使い方や注意点を初心者向けにわかりやすく解説

はじめに

JavaScriptで関数を定義するとき、引数に値が渡されなかった場合の動作をどのように設計するかは大切なポイントです。
何かしらの初期値を設定しておかないとエラーになったり、意図しない挙動を招いたりすることがあるからです。
そこで便利に使えるのがデフォルト引数という仕組みです。
これは関数側であらかじめ標準の値を設定することで、呼び出し側が引数を省略しても、問題なく動作するようにする方法を指します。

たとえば、ユーザーが入力フォームで値を入れなかったときに自動的に“なし”という文字列を設定したり、数値が指定されていないときは“0”を割り当てるといったケースが考えられます。
こうした状況をスムーズに処理したい場合、デフォルト引数がとても役立ちます。

本記事では、初心者の皆さんが混乱しやすい「デフォルト引数とはいったい何なのか」「どう使えばよいのか」「どんな注意点があるのか」を解説します。
実際の開発現場でよくあるシーンにも触れながら、基本構文と合わせて応用的な使い方まで紹介していきます。

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

  • デフォルト引数の基本的な構文とメリット
  • 実務でよくある活用シーン (フォームやAPI呼び出しなど)
  • 分割代入やレストパラメータなど、他の機能と組み合わせる方法
  • コード例を通じた具体的な使用イメージ
  • 注意点やトラブルを避けるためのポイント

ここから先は、コードを書く初心者の皆さんでも理解しやすいように平易な言葉で解説を進めていきます。
技術用語はできるだけ噛み砕いてお伝えするので、ぜひ一緒に学んでみてください。

JavaScriptにおけるデフォルト引数の概要

JavaScriptにおけるデフォルト引数は、関数の定義時に引数の初期値を設定しておく仕組みです。
呼び出し側が何も値を渡さなかったり、undefinedを指定したりした場合でも、あらかじめ設定された初期値が利用されます。

従来のコードでは、引数が未指定の場合にif文や論理演算子などを使い、開発者が手動で初期値をセットしていました。
しかし、デフォルト引数があることで、より読みやすくシンプルなコードを書くことができます。

たとえば、ユーザー情報を登録するときに、国や地域の値が未定の場合は“Japan”を割り当てたいというケースを考えてみましょう。
デフォルト引数を使うと、わざわざ条件分岐を書かなくても、関数宣言の部分で国名を“Japan”に指定できるのです。

デフォルト引数はモダンなJavaScriptの一部として、多くのプロジェクトで活用されています。
後述する構文を一度覚えておけば、関数の使い勝手が格段に良くなるでしょう。

なぜデフォルト引数が必要なのか

デフォルト引数を使う意義を明確にするために、従来の方法と比較してみます。
昔ながらのやり方としては、関数の内部で「もし引数がundefinedなら代わりにXを使う」という分岐を設けるパターンが一般的でした。

function greet(name) {
  // 古いスタイル:手動でチェック
  name = name === undefined ? "ゲスト" : name;
  console.log("こんにちは、" + name + "さん");
}

この方法でも動作自体は問題ありませんが、分岐が増えれば増えるほどコードが冗長になりがちです。
さらに、複数の引数で同様の処理を行う場合、同じようなパターンの記述が重複してしまうでしょう。

デフォルト引数が登場すると、引数の初期値を宣言的に定義できるようになりました。
これにより、コードの可読性が向上し、意図が明確になります。
また、関数を呼び出す側も「引数が省略できるんだな」という点を一目で理解できます。

コードが複雑化すると、小さな省略ミスでも不具合の原因になります。
デフォルト引数を積極的に活用することで、そういったバグを未然に防げるのは大きなメリットといえるでしょう。

デフォルト引数の基本的な構文

デフォルト引数の構文はとてもシンプルです。
関数定義のパラメータ部分でparameter = defaultValueという形にするだけで、未指定のときはdefaultValueが使われます。

function greet(name = "ゲスト") {
  console.log("こんにちは、" + name + "さん");
}

// 引数未指定
greet(); // こんにちは、ゲストさん

// 引数を指定
greet("太郎"); // こんにちは、太郎さん

上記の例では、name引数が省略されたとき、自動的に「ゲスト」という文字列が利用されます。
このように、宣言時にイコール(=)とともに初期値を指定するだけで完結するのが魅力です。

なお、デフォルト引数の値には式を使用できます。
文字列リテラルだけではなく、数値やオブジェクト、さらには呼び出し時点での計算結果なども指定可能です。
たとえば、今の時刻を自動でセットしたいという場合も、あらかじめDate.now()をデフォルト値にすることができます。

デフォルト引数を使った基本的なコード例

ここではもう少し具体的な例を見てみましょう。
たとえば、メッセージを表示する簡単な関数を考えます。
未指定の引数に対してデフォルト引数を設定しておくと、呼び出しが多様化しても安全に扱えます。

function showMessage(title = "お知らせ", body = "内容が未設定です") {
  console.log("【" + title + "】");
  console.log("本文:", body);
}

// 引数をすべて省略
showMessage();

// bodyだけ指定
showMessage("注意", "サーバーは深夜に再起動します。");

// titleだけ指定
showMessage("確認事項");

上記コードでは、titlebodyの両方にデフォルト値を持たせています。
呼び出し側が省略しても問題なく動作しますし、個別に値が指定された場合は、それを上書きして処理してくれます。

また、デフォルト引数にオブジェクトを設定するようなケースもよくあります。
オプション設定をまとめたオブジェクトを引数として受け取るとき、何かしらのプロパティが足りない場合でも動作するように、あらかじめ空オブジェクトを初期値に設定する手法があります。

function initConfig(options = {}) {
  console.log("設定内容:", options);
  // 必要に応じて内部でoptionsを扱う
}

このように、デフォルト引数を活用することで、関数呼び出しの柔軟性を高めながらコードをすっきり書けるようになります。

複数の引数を扱うときのデフォルト値

複数の引数を持つ関数で、それぞれにデフォルト引数を設定したいケースもあります。
たとえば、数値を加算する関数を用意し、第一引数が未指定の場合は0、第二引数が未指定なら1といった初期値を割り当てる方法を見てみましょう。

function addValues(a = 0, b = 1) {
  return a + b;
}

console.log(addValues());       // 1
console.log(addValues(5));      // 6
console.log(addValues(5, 10));  // 15

これにより、第一引数と第二引数の両方が省略されたときは0 + 1となり、結果として1が返されます。
利用者が必要に応じて引数を指定すれば、その値が優先される仕組みです。

このように引数の個数が増えても、デフォルト引数があれば未指定部分を手動で補完する必要がほとんどなくなります。
ただし、一度にあまりに多くのデフォルト引数を設定すると、かえって分かりにくくなる場合もあるので、バランスが重要です。

省略できる引数とオプションパラメータ

開発を進めると、「引数は4つあるけれど、ほとんどの場合2つしか使わない」といった状況が出てきます。
こうした場面では、すべての引数にデフォルト値を設定しておくと、利用者は必要な引数だけを指定し、不要な部分は省略できるようになります。

たとえば、以下のように複数のパラメータを用意し、それぞれデフォルト値を割り当てる場合です。

function createUser(name, age, country = "Japan", job = "Not Provided") {
  console.log("名前:", name);
  console.log("年齢:", age);
  console.log("国:", country);
  console.log("仕事:", job);
}

// countryとjobが省略される
createUser("太郎", 20);

// 全引数指定
createUser("花子", 30, "USA", "Engineer");

上記では第三引数と第四引数に初期値を設定しておくことで、利用者はその2つを省略できます。
このように、デフォルト値を活用すると、関数の使い勝手が格段に良くなるでしょう。

ただし、デフォルト引数をつけすぎると、どの引数がオプションでどれが必須なのか把握しづらくなることがあります。
後述する注意点のセクションで、引数の設計が複雑になるリスクについても補足していきます。

実務での活用シーン

実務において、デフォルト引数が活躍する場面は意外と多いです。
コードを読みやすくするだけでなく、複数プロジェクトで流用しやすい共通のユーティリティ関数を作りやすくなるなどのメリットがあります。
ここからは、具体的にどんなシーンで重宝されるのかを見てみましょう。

ブラウザ側のプログラムだけでなく、サーバーサイドJavaScriptを扱う場合にも、デフォルト引数は有用です。
APIで受け取るデータに欠落があったとき、関数側で想定したデフォルト値を使う設計にしておけば、エラーを避けながら処理を進められます。
加えて、フロントエンドではユーザー入力が常に保証されないケースも少なくありません。
そのときにもデフォルト引数は、動作を安全に保つ役割を果たします。

また、ライブラリやフレームワークの内部でも、複数のパラメータを管理する際にデフォルト値が設定されていることが多々あります。
これにより、利用者が最低限のオプションだけを指定すれば動作するようにできるのです。
デフォルト引数の概念を理解しておくと、外部ライブラリを使うときにも読み解きやすくなるでしょう。

フォーム入力の未入力対応

ブラウザアプリケーションでフォームを作成するとき、ユーザーが項目を未入力のまま送信するケースはよくあります。
そんなとき、サーバーサイドで値を受け取り、もし未入力なら何かしらの初期値を設定したい場合にデフォルト引数が便利です。

function processForm(name = "名無し", age = 0) {
  // name と age が未入力の場合、それぞれ初期値が使われる
  console.log("入力された名前:", name);
  console.log("入力された年齢:", age);
}

バックエンドに送信されたデータを受け取る関数で、こうした設定をしておくと、「未入力」であることをシステム側が自然に受け取りつつ、
初期値を適用した上で処理を継続できるようになります。

これにより、開発者が「入力チェック → エラー検出 → 初期値セット」のような面倒な手順を省ける場合もあるのです。
もちろん、バリデーションロジックなどが別に必要なこともありますが、その補助としてデフォルト引数を併用すると効率が良くなるでしょう。

API呼び出しのオプション設定

外部APIや内部APIを呼び出す際、APIコール用の関数を用意することがあります。
このとき、関数内で必要なオプション情報を指定しなかった場合の初期値として、デフォルト引数を活用する方法は非常に多いです。

たとえば、タイムアウト時間やリトライ回数、ログ出力の有無などを引数として受け取る関数を考えてみましょう。
これらは設定しなくても動くケースが多いため、デフォルト値を持たせておきたい場合が多々あります。

function callApi(endpoint, {
  timeout = 5000,
  retries = 3,
  log = false
} = {}) {
  if (log) {
    console.log("API呼び出し:", endpoint);
  }
  // 実際のAPI呼び出し処理(タイムアウトやリトライなど)を実装
}

ここでは、オプションをオブジェクトとして受け取り、そのプロパティにデフォルト値を設定しています。
未指定のプロパティがあっても動作するようになっているのがポイントです。

このような設計にしておくと、呼び出し側は最小限の情報だけを渡せばよく、追加の設定が必要なときだけオプションを指定する形にできます。
結果的に、呼び出し回数が増えたときもコードが見やすくなるメリットが得られます。

デフォルト引数と他の機能との組み合わせ

JavaScriptでは、デフォルト引数だけでなく、分割代入やレストパラメータといった便利な仕組みもあります。
それらを組み合わせると、コードをより柔軟に書くことができるでしょう。
ここでは、特に汎用性の高い組み合わせをいくつか紹介してみます。

分割代入を使えば、オブジェクトや配列の中身を直接取り出して変数に割り当てることができます。
また、レストパラメータを使うと可変長の引数をまとめて配列として受け取れるので、引数の数が決まっていない関数を定義する際に便利です。

これらの機能とデフォルト引数を併用することで、開発の自由度はさらに高まります。
複雑なデータ構造や柔軟なパラメータ設計が要求されるプロジェクトで、特にその効果を実感できるはずです。

分割代入との組み合わせ

分割代入は、関数の引数にも応用することができます。
たとえば、関数にオブジェクトを渡し、そのオブジェクトの特定のプロパティにデフォルト引数を設定しておく、という方法です。

function displayUserInfo({ name = "名無しさん", age = 0 } = {}) {
  console.log("名前:", name);
  console.log("年齢:", age);
}

displayUserInfo({ name: "太郎", age: 25 });
displayUserInfo({});
displayUserInfo();

上記の例では、関数の引数自体をオブジェクトとして受け取り、その中からnameageを分割代入で取り出し、
両方にデフォルト値を設定しています。
もしオブジェクトが空だったり、引数が渡されなかったりしてもエラーにならず、設定したデフォルト値が利用されます。

このように、分割代入とデフォルト引数を組み合わせることで、コードの記述量を抑えつつ読みやすい設計が可能になります。
データの構造が複雑になるほど、この方法が役立つでしょう。

レストパラメータとの組み合わせ

関数定義で...restの形で受け取るレストパラメータは、可変長の引数をまとめて配列にして扱う仕組みです。
デフォルト引数との組み合わせ例としては、「最初の1つか2つの引数には明示的な初期値を与え、それ以外はレストパラメータで受け取る」といったパターンがあります。

function sampleFunction(a = 10, b = 20, ...rest) {
  console.log("a:", a);
  console.log("b:", b);
  console.log("rest:", rest);
}

sampleFunction();
sampleFunction(1);
sampleFunction(1, 2, 3, 4, 5);

この例では、abにデフォルト値を設定し、それ以外の引数はすべてrestとして配列にまとめられます。
呼び出し方次第で引数の数を可変にしつつ、abの初期値を活用できるのがポイントです。

実際のプロジェクトでは、引数の構成があいまいな時点で設計をするのはリスクもありますが、
決まりきった部分だけをデフォルト引数で押さえ、残りをレストパラメータで柔軟に扱うという発想がハマるケースも存在します。

デフォルト引数を使うときの注意点

デフォルト引数は非常に便利ですが、いくつか注意すべき点もあります。
正しく理解しておかないと、「デフォルト値のつもりが意図しない値が入ってしまう」「引数の設計がややこしくなり、他の開発者が読みづらい」といった問題が起きるかもしれません。

引数が多すぎる関数にたくさんのデフォルト引数を設定すると、本来の必須項目が埋もれてしまい、保守性が下がる可能性もあります。
また、後述するような「評価タイミング」や「falsy値」との混同による想定外の挙動にも注意が必要です。

開発者同士でコードをレビューするときは、「なぜここにデフォルト引数を設定しているのか?」という意図を共有することが大切です。
よくある疑問点を含め、これからさらに詳しく見ていきましょう。

値の再評価に関する挙動

デフォルト引数の評価タイミングは、関数が呼び出されるたびに行われます。
つまり、デフォルト値に関数呼び出しやオブジェクト生成を仕込んでおくと、呼び出すたびに新しい値が作られる点を知っておくとよいでしょう。

たとえば、デフォルト引数にオブジェクトを設定したとき、関数が呼ばれるたびにそのオブジェクトが新規で生成されます。
意図せず「使い回し」を想定していると、思わぬバグにつながるかもしれません。

function createObject(data = {}) {
  // 呼び出すたびに別のオブジェクトが生成される
  return data;
}

この挙動を理解していないと、「デフォルト値だから同じオブジェクトを使い回すだろう」と思い込み、
データの共有や変更が予想外に振る舞う可能性があります。
もしオブジェクトを共有したいなら、グローバル変数や外部スコープなど、別の仕組みを利用する必要があるでしょう。

falsy値との混同に注意

JavaScriptでは、false, 0, ""(空文字), null, undefined, NaNなどはfalsyと呼ばれ、
条件式の中ではfalseと同等に扱われます。
以前は、こういったfalsyの扱いを利用して||(論理OR)などでデフォルト値を付ける方法がよく使われてきました。

しかし、||を使った短絡評価では、0""といった値も「未指定」とみなされてしまいます。
たとえば0という値を有効な数値として扱いたいのに、デフォルト値を強制的に使ってしまうという問題が発生します。

function useFallback(num) {
  num = num || 100; // falsy判定による置き換え
  return num;
}

console.log(useFallback(0));   // 100が返されてしまう

デフォルト引数を使えば、上記のような問題は起こりません。
引数がundefinedの場合のみ初期値を適用し、0や空文字にはそのまま指定された値を適用します。
この違いがあるため、意図しない上書きが行われにくいのが、デフォルト引数を推奨する大きな理由の一つです。

論理ORによる短絡評価とデフォルト引数は振る舞いが異なります。 「0は正当な値なのに、デフォルト値に置き換わってしまう」などのミスが起きないように気をつけましょう。

パフォーマンスへの影響

一般的な規模のコードでは、デフォルト引数の使用でパフォーマンスが大きく低下することはほぼ考えにくいです。
通常の関数呼び出しと同程度のコストしかかからず、たとえ一度に多くの関数が呼ばれたとしても、大きな問題になるケースは少ないでしょう。

ただし、非常に高頻度で呼び出される関数の中で複雑な式をデフォルト値として設定すると、呼び出しのたびに評価が行われることを意識する必要があります。
たとえば、重い処理を含む関数呼び出しをデフォルト値にしている場合、それがパフォーマンスのボトルネックになる可能性は否定できません。

大規模なシステムでは、微細な最適化が必要な箇所も出てきます。
その際はプロファイリングツールなどを用いて、実際にどの部分が遅いのかを調べた上で対策を検討するのが良いでしょう。
通常はデフォルト引数だけが原因で性能問題を引き起こすことは少ないため、過度に警戒する必要はありません。

デフォルト引数を使わずに対処する方法

デフォルト引数は便利ですが、何らかの理由で使用を控えたいケースもあるかもしれません。
プロジェクトのコーディング規約や、対応している環境が限られている場合など、いろいろな事情が考えられます。
そこで、デフォルト引数を使わずに代替手段を用いる場合の一例を紹介します。

昔ながらのやり方としては、以下のように関数内で条件分岐を設ける方法があります。
ただし、これを多用するとコード量が増え、可読性も下がりやすい点は覚えておきましょう。

function myFunction(a, b) {
  if (a === undefined) {
    a = 10;
  }
  if (b === undefined) {
    b = 20;
  }
  return a + b;
}

このように、=== undefinedで判定をしている部分をデフォルト引数に置き換えられるなら、その方がスッキリするでしょう。

短絡評価を使ったパターン

デフォルト引数が登場する前は、短絡評価(論理ORなど)をよく使って初期値を設定していました。
しかし前述の通り、0や空文字など、falsy値を意図しない形で上書きしてしまうリスクがあります。

function setNum(num) {
  num = num || 100;
  return num;
}

// numが0のときも100になる
console.log(setNum(0));

これを回避するには、厳密に「undefinedだけをチェックしたい」場合、以下のように条件を工夫する手があります。

function setNum(num) {
  if (num === undefined) {
    num = 100;
  }
  return num;
}

いずれにせよ、ロジックが多少冗長になってしまうため、モダンなJavaScript環境であればデフォルト引数の利用が推奨される場面が多いでしょう。

オブジェクトのマージによる初期化

オブジェクトを引数に渡すとき、プロパティごとにデフォルト値を設定したいというケースがあります。
デフォルト引数を使わない方法としては、「オブジェクトを受け取った後に、予め用意しておいたデフォルト設定オブジェクトとマージする」手法が存在します。

function setup(options) {
  const defaults = {
    color: "blue",
    size: "M"
  };
  const config = {
    ...defaults,
    ...options
  };
  console.log(config);
}

setup({ size: "L" }); // colorはblueのまま

スプレッド構文(...)を使って、既定の設定値と受け取ったオプションを合体させるやり方です。
これにより、デフォルト引数を使わずとも「未指定のプロパティにはデフォルトを適用する」仕組みを実現できます。

ただし、引数がundefinedそのものだった場合は、...optionsがエラーを引き起こす可能性があるため、適切な分岐や初期化をする必要があります。
その点でも、やはりデフォルト引数でオブジェクトを初期化しておいた方がスムーズに書ける場面は多いでしょう。

よくある疑問

デフォルト引数を実際に使っていると、いくつか疑問が湧いてくることがあります。
ここでは、初心者の皆さんが特に迷いやすいポイントを取り上げながら、簡単に解説していきます。
「自分と同じ疑問だ」と感じた部分があれば、ぜひ参考にしてみてください。

たとえば、デフォルト引数に関数式や無名関数を割り当てるときの書き方や、配列を使いたいときにどうするのかなど、バリエーションは多岐にわたります。
基本的にはイコールの右側にJavaScriptの「式」が書けると考えて問題ありませんが、実際にコードを書く前にシンプルな例で試してみるのがおすすめです。

デフォルト引数は任意の型を使える?

デフォルト引数では、JavaScriptで扱える型なら基本的にどれでも指定できます。
数値や文字列はもちろん、オブジェクト、配列、関数式、クラスインスタンスなど、さまざまなパターンに対応可能です。

function runCallback(callback = () => console.log("デフォルトの処理")) {
  callback();
}

runCallback(); // デフォルトの処理
runCallback(() => console.log("カスタム処理"));

この例のように、デフォルト値として無名関数をそのまま指定することも珍しくありません。
ただし、あまりにも複雑な処理を書き込みすぎると、可読性が下がる懸念があるので注意しましょう。
必要に応じて、別に用意した変数や関数を割り当てる方法も検討してみるとよいです。

関数式や無名関数でも使える?

デフォルト引数の仕組みは、関数宣言だけに限らず、関数式や無名関数(アロー関数)にも同様に使えます。

const multiply = function(a = 1, b = 1) {
  return a * b;
};

const divide = (a = 1, b = 1) => a / b;

console.log(multiply());    // 1
console.log(multiply(2,3)); // 6
console.log(divide());      // 1
console.log(divide(10,2));  // 5

上記のように、どんな形の関数でもパラメータ部分があれば、そこに=を使ってデフォルト値を設定できます。
アロー関数でも記述スタイルが変わるだけで、原理的には同じです。

関数宣言か関数式かを問わず、引数が存在するすべての関数に対してデフォルト値を設定することができます。

まとめ

ここまで、JavaScriptのデフォルト引数について幅広く解説してきました。
以下のようなポイントを押さえておけば、日常的な開発でデフォルト引数を上手に活用できるはずです。

  • 関数定義でparameter = defaultValueと書くだけで、引数が未指定の際に初期値をセットできる
  • 多数の引数を扱う場合、どれが必須でどれがオプションか明確にすることが重要
  • オブジェクトや関数式など、あらゆる型をデフォルト値に設定可能
  • falsy値との混同を避けられるため、||&&などの短絡評価よりも意図が明確
  • 評価タイミングに注意し、オブジェクトを使い回したい場合などは別の方法が必要

JavaScriptではさまざまな書き方が存在しますが、デフォルト引数の採用はコードの可読性と保守性を高めるうえでメリットが大きいです。
特に初心者の皆さんにとっては、複雑な条件分岐を使わずに短いコードで動作を補完できるため、ぜひ習得しておきたいテクニックといえるでしょう。

今後、複数のプロジェクトを触るときに「この関数は必須引数がどれで、オプション引数がどれなのか?」という疑問が出るはずです。
そうした場面でデフォルト引数を使って設計しておけば、今後の修正や機能拡張がスムーズになります。

みなさんも、ぜひ自分のコードの中でデフォルト引数を活用してみてください。

JavaScriptをマスターしよう

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