可変長引数って何者?
可変長引数(かへんちょうひきすう)は、
「引数が何個来るか分からないけど、とりあえず全部受け取りたい」 ときに使う仕組みです。
JavaScript では ...args のように、引数名の前に ... をつけて書きます。
この ... がついた引数には、「残りの引数が配列として全部入る」と思ってください。
一番シンプルな可変長引数の例
いくつ渡しても全部足す関数
まずは「渡された数を全部足す」関数を作ってみます。
function sum(...numbers) {
console.log(numbers); // ここで中身を確認してみる
}
sum(1, 2, 3); // [1, 2, 3]
sum(10, 20); // [10, 20]
sum(5, 6, 7, 8, 9); // [5, 6, 7, 8, 9]
JavaScriptnumbers には、渡された引数が配列として入っています。
これを使って合計を出してみましょう。
function sum(...numbers) {
let total = 0;
for (const n of numbers) {
total += n;
}
return total;
}
console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20)); // 30
console.log(sum(5, 6, 7, 8, 9)); // 35
JavaScriptここが重要です。...numbers は「引数を配列として受け取る」ためのもの。
何個来ても、来なくても、とりあえず配列になる。
可変長引数のルール
「最後の1つだけ」にしか使えない
可変長引数は、引数リストの「一番最後」にしか書けません。
function func(a, b, ...rest) {
// OK
}
JavaScriptこれはOKですが、
function func(...rest, a) {
// エラー
}
JavaScriptこれはエラーになります。
「残り全部」を受け取るので、その後ろにまだ引数があると意味が破綻するからです。
引数が0個でもちゃんと動く
可変長引数は、引数が1つも渡されなくても動きます。
function sum(...numbers) {
console.log(numbers);
}
sum(); // []
JavaScriptこの場合、numbers は「空配列」です。
「何も来なかった」ということが、配列の長さ 0 で表現されます。
可変長引数と普通の引数の組み合わせ
「最初のいくつかは固定、それ以降は全部まとめて」
例えば、「最初のメッセージ」と「それ以降の値」を一緒にログに出したい関数。
function logWithLabel(label, ...values) {
console.log("[" + label + "]", values);
}
logWithLabel("INFO", 1, 2, 3);
// [INFO] [1, 2, 3]
logWithLabel("DEBUG", "a", "b");
// [DEBUG] ["a", "b"]
logWithLabel("EMPTY");
// [EMPTY] []
JavaScriptここでは、
label は普通の引数(必須)...values は「2個目以降の引数を全部まとめた配列」
という役割分担になっています。
ここが重要です。
可変長引数は「固定の引数+残り全部」という形で使うと、とても表現力が高くなる。
可変長引数と arguments の違い
昔からある arguments と、今どきの ...args
関数の中には、昔から arguments という「擬似配列」がありました。
function oldSum() {
console.log(arguments);
}
oldSum(1, 2, 3); // { 0: 1, 1: 2, 2: 3, length: 3, ... }
JavaScriptarguments は「渡された引数全部」が入っていますが、
配列ではなく「配列っぽいオブジェクト」です。
一方、可変長引数 ...args は、最初から「本物の配列」です。
function newSum(...numbers) {
console.log(numbers); // [1, 2, 3]
}
JavaScript配列なので、map, filter, reduce などがそのまま使えます。
function sum(...numbers) {
return numbers.reduce((acc, n) => acc + n, 0);
}
JavaScriptここが重要です。
今から新しく書くコードでは、arguments よりも ...args を使うのが基本。
理由は「配列として扱える」「アロー関数でも使える」から。
実務での可変長引数の使いどころ
ログ関数を自作する
コンソールログをラップして、
「ラベル付きログ」を作る例です。
function log(level, ...messages) {
const time = new Date().toISOString();
console.log(time, "[" + level + "]", ...messages);
}
log("INFO", "サーバー起動", { port: 3000 });
log("ERROR", "接続失敗", "リトライします");
JavaScriptここでは、
level はログレベル(INFO, ERROR など)...messages は「それ以降の引数を全部まとめた配列」console.log に渡すときは ...messages を展開して渡す
という使い方をしています。
配列を受け取る関数を「引数バラバラ」でも呼べるようにする
例えば、Math.max は可変長引数のように使えます。
Math.max(1, 5, 3); // 5
JavaScript自分で似たような関数を書くときにも、...args が使えます。
function max(...numbers) {
return numbers.reduce((m, n) => (n > m ? n : m), -Infinity);
}
console.log(max(1, 5, 3)); // 5
JavaScript配列を持っている場合は、スプレッド構文と組み合わせます。
const arr = [1, 5, 3];
console.log(max(...arr)); // 5
JavaScript可変長引数で気をつけたいこと
「何でもかんでも可変長にしない」
可変長引数は便利ですが、
何でも ...args にすると「この関数は何を期待しているのか」が分かりにくくなります。
例えば、
function doSomething(...args) {
// args[0] はたぶんこれで、args[1] はたぶんこれで…
}
JavaScriptのようなコードは、読み手にとってつらいです。
ここが重要です。
可変長引数は「本当に“数が可変”であることに意味があるとき」にだけ使う。
それ以外は、普通に引数を明示的に並べた方が読みやすい。
初心者として「可変長引数(…args)」で本当に押さえてほしいこと
可変長引数は、
function func(...args) { }
JavaScriptのように書き、
「渡された引数を配列として受け取る」ための仕組み です。
ポイントは、
最後の引数にしか書けない
引数が0個でも空配列として動く
配列なので for, for...of, map, filter, reduce などがそのまま使えるarguments よりも今どきは ...args を使う
まずは、
「全部足す sum 関数」や「ラベル付きログ関数」を自分の手で書いてみてください。
function sum(...nums) {
// ここを自分で書いてみる
}
JavaScriptこの小さな一歩で、
「引数の数に縛られない関数」を設計できる感覚が、ぐっと近づいてきます。
