JavaScript | ES6+ 文法:関数の進化 – arguments 非対応

JavaScript
スポンサーリンク

arguments 非対応とは何か

アロー関数は「自分専用の arguments(可変長引数の擬似配列)」を持ちません。ここが重要です:従来の function なら arguments で渡された全引数にアクセスできますが、アロー関数はそれができません。代わりに“設計的に正しい”手段である rest パラメータ(...args)を使います。例外的に、アロー関数が“通常の関数の内側”にある場合は、外側の function が持つ arguments を参照できます(レキシカルにキャプチャされるため)が、これは原則避けるべきです。

// 従来の function は arguments を持つ
function sum() {
  return Array.from(arguments).reduce((s, n) => s + n, 0);
}

// アロー関数は arguments を持たない
const sumArrow = () => {
  // return Array.from(arguments).reduce(...) // NG: arguments がない
  return 0;
};
JavaScript

正しい代替:rest パラメータ(…args)

rest パラメータは“受け取った引数を配列として受理”する構文で、アロー関数でも使えます。ここが重要です:arguments よりも型安全・可読で、配列メソッドをそのまま使えます。

// 可変長引数を安全に受け取る
const sum = (...nums) => nums.reduce((s, n) => s + n, 0);
console.log(sum(1, 2, 3)); // 6

// 先頭は必須、後続は任意も簡単
const tag = (label, ...parts) => `${label}:${parts.join("-")}`;
console.log(tag("id", 10, 20, 30)); // "id:10-20-30"
JavaScript

複合パラメータとも組み合わせられます。分割代入やデフォルト引数との相性が良く、意図が明確になります。

const formatUser = ({ id, name = "" }, ...flags) =>
  `${id}:${name.trim()}${flags.length ? ":" + flags.join(",") : ""}`;
JavaScript

呼び出し側は spread(…)で渡す

呼び出し側が配列の要素を“引数として展開”するには spread を使います。ここが重要です:rest は“受け取り側”、spread は“渡し側”。両者を組み合わせると、柔軟で読みやすい可変長処理になります。

const nums = [10, 20, 30];
const sum = (...xs) => xs.reduce((s, n) => s + n, 0);

console.log(sum(...nums)); // 60(配列を展開して渡す)
JavaScript

外側の arguments を“拾える”が原則使わない

アロー関数は自前の arguments を持ちませんが、通常の function の内側で書いた場合、その外側 function の arguments を参照できます。ここが重要です:動くが紛らわしく、保守性が下がるため推奨しません。rest に置き換えましょう。

function outer() {
  // outer の arguments を内側のアローが参照してしまう例
  const inner = () => Array.from(arguments).join("-");
  return inner();
}
console.log(outer(1, 2, 3)); // "1-2-3"(動くが読みづらい)

// 推奨:outer も inner も rest にする
function outer2(...args) {
  const inner = (...xs) => xs.join("-");
  return inner(...args);
}
console.log(outer2(1, 2, 3)); // "1-2-3"
JavaScript

ありがちな落とし穴と対策(重要ポイントの深掘り)

アロー関数で arguments を使おうとしてエラー(ReferenceError)や undefined な挙動に遭遇しがちです。対策は一貫して“rest に置き換える”。また、arguments は配列ではなく“擬似配列”なので、配列メソッドが直接使えず、Array.from やスプレッド変換が必要でした。rest は最初から配列なので余計な変換が不要です。さらに、arguments はすべての引数を無差別に含むため、意図が曖昧になりがち。関数のインターフェース(必要な引数・可変部分)をパラメータで明確化するほうが安全です。

// NG: アローで arguments を前提に書いてしまう
const concat = () => Array.from(arguments).join(""); // 失敗

// OK: rest で明示
const concat2 = (...parts) => parts.join("");
JavaScript

実務レシピ(可変長と配列処理をスマートに)

可変長のバリデーション+計算

const average = (...nums) => {
  const vals = nums.filter(n => Number.isFinite(n));
  return vals.length ? vals.reduce((s, n) => s + n, 0) / vals.length : 0;
};
JavaScript

先頭は固定、後続はオプションのパターン

const buildUrl = (base, ...params) =>
  `${base}?` + params.map(encodeURIComponent).join("&");
console.log(buildUrl("/search", "q=js", "page=2")); // "/search?q=js&page=2"
JavaScript

引数の“形”を明示(分割代入+rest)

const render = ({ id, name }, ...mods) =>
  `${id}:${name}${mods.length ? " [" + mods.join(", ") + "]" : ""}`;
JavaScript

まとめ

アロー関数は arguments を持たないため、“可変長引数は rest(…args)を使う”が原則です。呼び出し側は spread(…)で配列を展開する。外側の arguments をキャプチャできても、読みづらく誤解を招くので避ける。rest は最初から配列で扱いやすく、型安全・可読性・保守性に優れます。これを徹底すれば、初心者でもアロー関数で柔軟かつ明快なインターフェースを設計でき、arguments 依存の罠から卒業できます。

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