JavaScript の関数の引数の数を知る方法
まずは結論から。JavaScript の関数には次の2つの「引数の数」を調べる方法があります。
.length: 関数が「定義されている引数の数」arguments.length: 関数を「呼び出したときに実際に渡された引数の数」
この2つはよく混同されるので、例を使って直感的に理解しましょう。
関数の .length は「設計図の数」
関数を作るときに書いた引数の数が返ってきます。実際に何個渡したかは関係ありません。
function add(a, b, c) {
return a + b + c;
}
console.log(add.length); // 3 ← 設計図上は3つ
console.log(add(1, 2).length); // これはエラー(関数の戻り値に .length はない場合が多い)
JavaScript- ポイント:
.lengthは「関数そのもの」に使います。関数の戻り値に使うものではありません。
arguments.length は「実際に渡された数」
関数の中で使う「特別な配列っぽいもの」です。呼び出し時に何個引数が来たかを教えてくれます。
function showArgs() {
console.log(arguments.length);
}
showArgs(); // 0
showArgs(10); // 1
showArgs(1, 2, 3, 4); // 4
JavaScript- ポイント:
argumentsは「配列風」ですが、完全な配列ではありません(mapなどは使えません)。必要ならArray.from(arguments)で配列に変換できます。
デフォルト引数は .length の数に含まれない
引数に「デフォルト値」を付けると、そこから先の引数は .length の数に含まれなくなります。
function greet(name = "guest", age) {}
console.log(greet.length); // 0
JavaScript- なぜ? 最初の引数
nameにデフォルトがあるため、.lengthはそこで打ち切られます。以降(age)も数えません。
もう少し直感的な例を。
function f(a, b = 10, c, d) {}
console.log(f.length); // 1 ← bにデフォルトがあるので、aまでで打ち切り
JavaScript可変長引数(rest)は .length に含まれない
... を使った引数は、何個でも受け取れる仕組みです。これも .length には含まれません。
function sum(start, ...nums) {
// nums は [渡された残り全部] の配列
}
console.log(sum.length); // 1 ← restは数えない
JavaScript- 使い分け: 「残り全部まとめて受け取りたい」なら
...nums、「何個渡されたかだけ知りたい」ならarguments.length。
初心者向けの例題で理解を固める
例題1: .length と arguments.length の違い
function demo(a, b, c) {
console.log("定義された数:", demo.length);
console.log("渡された数:", arguments.length);
}
demo(1); // 定義された数: 3 / 渡された数: 1
demo(1, 2, 3, 4); // 定義された数: 3 / 渡された数: 4
JavaScript- 学び:
.lengthは設計図、arguments.lengthは実測値。
例題2: デフォルト引数の影響
function hello(name = "guest", age, city) {
console.log("定義された数:", hello.length);
}
hello(); // 定義された数: 0
JavaScript- 学び: 最初の引数にデフォルトがあると、そこから先は
.lengthで数えない。
例題3: rest と arguments の使い分け
function total(...nums) {
// 何個来ても受け取れる
console.log(nums.reduce((sum, n) => sum + n, 0));
}
total(1, 2, 3); // 6
total(5); // 5
JavaScript- 学び: 「引数全部を配列で扱いたい」なら rest。個数を知るだけなら
arguments.length。
ありがちなハマりポイントと回避法
- 「.length を信じすぎる」
.lengthは「定義の数」であって「実際の数」ではありません。入力チェックにはarguments.lengthを使いましょう。 - デフォルト引数で .length が急に小さくなる
最初の引数にデフォルトを付けた時点で.lengthはそこで切れます。必要なら「デフォルトは後ろに寄せる」か「入力チェックはarguments.length」に切り替えます。 argumentsを配列と勘違いする
ループはできますが、mapやfilterは使えません。配列にしたいならArray.from(arguments)。
自分で手を動かす小課題
- 入力の数で挙動を変える関数を作る
- 1個だけ来たらその値を返す
- 2個来たら足し算
- 3個以上来たら合計 ヒント:
arguments.lengthとArray.from(arguments)を使う
- デフォルト引数を使って、
.lengthの値がどう変わるか確認する- 引数の位置を変えながら
.lengthをconsole.logしてみる
- 引数の位置を変えながら
- rest でログ関数を作る
logAll(...msgs)で、渡されたメッセージを全部1行ずつ表示
まとめの一言
.lengthは設計図の数。arguments.lengthは実測の数。- デフォルト引数・rest は
.lengthのカウントに含まれない。
