概要
- 役割: 関数に渡された「可変個の引数」をひとつの配列として受け取る仕組み
- 書き方:
function fn(...args) { /* args は配列 */ }
- イメージ: 「残り全部まとめて受け取るカバン」。何個入ってきても配列で受け取れる
function logAll(...values) {
console.log(values); // 例: [1, 'hello', true]
}
logAll(1, 'hello', true);
JavaScript
基本の使い方とルール
- 最後に書く: rest パラメータは「引数リストの最後」に置く必要がある
function greet(greeting, ...names) {
for (const name of names) {
console.log(`${greeting}, ${name}!`);
}
}
greet('こんにちは', '田中', '佐藤'); // こんにちは, 田中! / こんにちは, 佐藤!
JavaScript
- 1つだけ: rest パラメータは「関数につき1つ」しか使えない
function bad(...a, ...b) {} // ❌ エラー
JavaScript
- 型は配列: 受け取ったものは配列なので、
map や filter などが使える
function sum(...nums) {
return nums.reduce((acc, n) => acc + n, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
JavaScript
- 引数が0個でもOK: 何も渡されないときは空配列になる
function countArgs(...args) {
console.log(args.length);
}
countArgs(); // 0
JavaScript
よくある混同:「rest」と「spread」の違い
- rest(まとめる): 引数や構造の「受け取り側」で、複数を「配列にまとめる」
function collect(...items) {
return items; // 受け取ったものを配列としてまとめる
}
JavaScript
- spread(ほどく): 配列やオブジェクトの「渡す側」で、まとめたものを「ほどいて展開」
const arr = [1, 2, 3];
console.log(Math.max(...arr)); // 3 ← 配列をバラして引数として渡す
const a = [1, 2];
const b = [3, 4];
const merged = [...a, ...b]; // [1, 2, 3, 4]
JavaScript
- 覚え方: rest は「受け皿」、spread は「ばら撒き」
実用例で身につける
1. 可変長の計算(合計・平均)
function average(...nums) {
if (nums.length === 0) return 0;
const total = nums.reduce((acc, n) => acc + n, 0);
return total / nums.length;
}
console.log(average(10, 20, 30)); // 20
JavaScript
2. 必須 + 任意の引数をスマートに受け取る
function makeList(title, ...items) {
console.log(`タイトル: ${title}`);
items.forEach((item, i) => console.log(`${i + 1}. ${item}`));
}
makeList('買い物', '牛乳', 'パン', '卵');
// タイトル: 買い物
// 1. 牛乳
// 2. パン
// 3. 卵
JavaScript
3. 第一引数は特別扱いして、残りをまとめる
function dispatch(command, ...args) {
switch (command) {
case 'add':
return args.reduce((a, b) => a + b, 0);
case 'join':
return args.join('-');
default:
return 'unknown command';
}
}
console.log(dispatch('add', 1, 2, 3)); // 6
console.log(dispatch('join', 'a', 'b')); // a-b
JavaScript
4. ロガーで柔軟なメッセージを作る
function logger(level, ...messages) {
const text = messages.join(' ');
console.log(`[${level}] ${text}`);
}
logger('INFO', '起動しました', 'ポート:', 3000);
// [INFO] 起動しました ポート: 3000
JavaScript
「arguments」との違いと注意点
- 配列かどうか:
arguments は「配列風」で、map などが直接使えない/...args は「本物の配列」
function oldStyle() {
// arguments は配列風オブジェクト
const arr = Array.from(arguments); // 変換が必要
return arr.join(',');
}
function modern(...args) {
return args.join(','); // すぐ使える
}
JavaScript
- アロー関数: アロー関数には
arguments がないので、可変長は rest を使う
const joinAll = (...parts) => parts.join('/');
JavaScript
- 関数長 (
length) の意味: rest を使うと、関数の length は「rest 以外の引数の数」を表す
function f(a, b, ...rest) {}
console.log(f.length); // 2
JavaScript
応用:配列・オブジェクトの構造での rest
const [first, ...others] = [10, 20, 30, 40];
console.log(first); // 10
console.log(others); // [20, 30, 40]
JavaScript
const user = { id: 1, name: 'Aki', role: 'admin', active: true };
const { name, ...meta } = user;
console.log(name); // 'Aki'
console.log(meta); // { id: 1, role: 'admin', active: true }
JavaScript
- 注意: 配列・オブジェクトの rest も「最後に一つだけ」。途中に置くことはできない
const [...a, last] = [1, 2, 3]; // ❌ エラー(最後じゃない)
JavaScript
練習問題(手を動かす)
// 入力例: stats(1, 5, 3) => { sum: 9, max: 5 }
function stats(...nums) {
// ここを書いてみよう
}
JavaScript
// joinWith('-', 'a', 'b', 'c') => 'a-b-c'
function joinWith(separator, ...parts) {
// ここを書いてみよう
}
JavaScript
// route('mul', 2, 3, 4) => 24
function route(cmd, ...args) {
// 'sum' は合計, 'mul' は掛け算, それ以外は 'unknown'
}
JavaScript
つまずきポイントのミニチェック
- 最後に置いた? rest は引数の最後に一つだけ
- 配列として扱っている?
map, filter, reduce が使える
- spreadと混ざってない? 受け取りは
...args、渡すときは ...arr