JavaScript | 可変長引数(rest パラメータ)

JavaScript JavaScript
スポンサーリンク

概要

  • 役割: 関数に渡された「可変個の引数」をひとつの配列として受け取る仕組み
  • 書き方: 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
  • 型は配列: 受け取ったものは配列なので、mapfilter などが使える
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

タイトルとURLをコピーしました