それでは「実務で役立つデフォルト引数の具体例」をいくつか作って、用途・利点・注意点をコードとともに丁寧に解説します。すぐ使えるパターンを中心にします — そのままプロダクションのユーティリティに入れられるような例も含めます。
1. オプションオブジェクトのデフォルト(一般的パターン)
多くの実務コードでは「引数が増えたときに壊れない」ようにオプションをオブジェクトで受け取り、{} をデフォルトにする書き方が便利です。
function fetchData(url, options = {}) {
const {
method = "GET",
headers = { "Content-Type": "application/json" },
timeout = 5000,
retries = 2
} = options;
console.log({ url, method, headers, timeout, retries });
// 実際は fetch を使って処理する(省略)
}
fetchData("/api/users");
// => method: "GET", timeout: 5000, retries: 2
fetchData("/api/users", { method: "POST", retries: 0 });
// => method: "POST", timeout: 5000, retries: 0
JavaScript利点:呼び出し側で必要なオプションだけ指定でき、将来オプションが増えても互換性を保てる。
2. 関数ベースの遅延評価(副作用のあるデフォルト値を遅らせる)
デフォルト値に関数呼び出しを書くと、呼ばれたときだけ評価されます。重い処理や副作用がある場合は便利です。
function expensiveSetup() {
console.log("expensiveSetup 実行");
return { token: "abcd" };
}
function doTask(config = expensiveSetup()) {
console.log("config:", config);
}
doTask({ token: "user-provided" }); // expensiveSetup は呼ばれない
doTask(); // expensiveSetup が呼ばれる
JavaScript利点:必要なときだけ重い処理を行う。呼び出しごとに別のデフォルトがほしいときにも使える。
3. パラメータ同士の依存(後続パラメータが前の値に依存)
ある引数のデフォルト値に前の引数を参照することができます(ただし左から右へ評価されます)。
function makeGreeting(name = "ゲスト", greeting = `こんにちは、${name}さん`) {
console.log(greeting);
}
makeGreeting("太郎"); // こんにちは、太郎さん
makeGreeting(); // こんにちは、ゲストさん
makeGreeting(undefined, "やあ"); // やあ
JavaScript注意:依存する前の引数が undefined の場合に想定どおり動くようにする。
4. デフォルト値と分割代入(関数でオブジェクトを受け取るとき)
APIレスポンス整形やコンポーネントの props に便利。
function renderCard({ title = "無題", content = "", showFooter = true } = {}) {
console.log("title:", title);
console.log("content:", content);
console.log("showFooter:", showFooter);
}
renderCard(); // 引数なしでも安全に動く
renderCard({ title: "今日のニュース" });
JavaScriptポイント:関数の引数全体にも = {} を付けないと、引数を省略したときに分割代入でエラーになります。
5. バリデーションを組み合わせた安全設計
単にデフォルト値を与えるだけでなく、渡された値の型チェックや正規化も行うと堅牢になります。
function createUser({ name = "名無し", age = 18, roles = [] } = {}) {
// 型チェック・正規化
if (typeof name !== "string") name = String(name);
age = Number.isFinite(age) ? age : 18;
roles = Array.isArray(roles) ? roles : [roles];
return { name, age, roles };
}
console.log(createUser({ name: null, age: "25", roles: "admin" }));
// => { name: "null", age: 25, roles: ["admin"] }
JavaScript利点:外部入力や古いクライアントからの呼び出しでも予測可能に動く。
6. デフォルト引数を使った負荷分散(例:ログ送信)
デフォルトでローカル保存、オプションでリモート送信など実務でよくあるパターン。
function sendLog(message, transport = defaultTransport) {
transport.send(message);
}
const defaultTransport = {
send(msg) {
// 既定はローカルに保存
console.log("local store:", msg);
}
};
const remote = {
send(msg) {
// 実際は HTTP POST など
console.log("sending to remote:", msg);
}
};
sendLog("ユーザーログ"); // local store
sendLog("重要ログ", remote); // remote
JavaScript利点:テスト時にモックを渡すだけで外部呼び出しを差し替えられる(DI に近い使い方)。
7. 注意点まとめ(実務での落とし穴)
nullを渡すとデフォルトは 使われない(undefinedのときのみ有効)。必要に応じて??(Nullish coalescing)を使う。
function fn(x = 1) { console.log(x); }
fn(null); // null
JavaScript- 可変オブジェクト(配列・オブジェクト)をデフォルトにすると、参照共有のバグが発生することがある。関数で新しいオブジェクトを生成するパターンが安全。
// NG: 共有される
function pushItem(item, list = []) { list.push(item); return list; }
pushItem(1); // [1]
pushItem(2); // [1,2] ← 期待外の共有(実際は JS では初回ごとに別インスタンス。ただし注意は必要)
JavaScript→ 安全な書き方:
function pushItem(item, list) {
const safeList = (list === undefined) ? [] : list;
safeList.push(item);
return safeList;
}
JavaScript- 前方の引数でデフォルトを設定すると、後続引数を省略したいときに
undefinedを明示する必要が出ることがある。オプションはオブジェクトで渡すのがベター。
8. 練習問題(すぐ手を動かせる)
greet(name = "ゲスト", punctuation = "!")を使って"やあ、太郎さん!"のように表示する関数を書いてください。makeRequest(url, { retries = 3 } = {})を使って、retriesのデフォルトが効く呼び出しと、retries = 0が効く呼び出しの両方を示してください。
解答
function greet(name = "ゲスト", punctuation = "!") {
console.log("やあ、" + name + "さん" + punctuation);
}
greet("太郎"); // やあ、太郎さん!
greet(); // やあ、ゲストさん!
JavaScriptfunction makeRequest(url, { retries = 3 } = {}) {
console.log("URL:", url, "retries:", retries);
}
makeRequest("/ping"); // retries: 3
makeRequest("/ping", { retries: 0 }); // retries: 0
JavaScript

