Blog icon indicating copy to clipboard operation
Blog copied to clipboard

[MDN] Rest 參數

Open ChaoLiou opened this issue 5 years ago • 0 comments

Rest 參數

  • rest 參數 語法讓函式接受不定量的參數, 並將全部參數視為一個 陣列, 表現出 variadic functions (這個詞來自 C, 指的是可以接受不定量參數的函式).

語法

function f(a, b, ...theArgs) {
  // ...
}

說明

  • 函式定義中最後一個參數可以加上 "..." 前綴, 讓剩下的參數都放置於一個標準的陣列. 函式中只有最後一個參數可以是 rest 參數.
function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

// 輸出:
// a, one
// b, two
// manyMoreArgs, ["three", "four", "five", "six"]

快速參考

  • 函式定義只可以有一個 ...restParam
foo(...one, ...wrong, ...wrong) // X
  • rest 參數必須是函式定義中最後一個參數.
foo(...wrong, arg2, arg3) // X
foo(arg1, arg2, ...correct) // O

rest 參數與 arguments 物件的不同處

  • 有三個不同處:
    • arguments 物件不是真的陣列, 而 rest 參數是 Array instances, 意思是 sort, map, forEachpop 都可以直接運用.
    • arguments 物件有特定的額外功能(像是 callee 屬性)
    • ...restParam 會將所有額外的參數綁到單一個陣列, 因此他不會包含任何具名的參數. arguments 物件包含所有參數 - 包括 ...restParam 裡面的所有東西.

arguments 到陣列

  • rest 參數用於減少 boilerplate code, 常見的是將參數集合轉換成陣列.
// 過去 "arguments" 可能會被轉成普通的陣列:

function f(a, b) {
  let normalArray = Array.prototype.slice.call(arguments);
  // -- 或 --
  let normalArray = [].slice.call(arguments);
  // -- 或 --
  let normalArray = Array.from(arguments);

  let first = normalArray.shift(); // OK, 給第一個參數
  let first = arguments.shift(); // ERROR (arguments 不是陣列)
}

// 現在你可以得到直接存取陣列的能力

function f(...args) {
  let normalArray = args;
  let first = normalArray.shift(); // OK, 給第一個參數
}

範例

使用 rest 參數

function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

// a, "one"
// b, "two"
// manyMoreArgs, ["three", "four", "five", "six"] <-- 注意, 它是一個陣列
myFun("one", "two", "three");

// a, "one"
// b, "two"
// manyMoreArgs, ["three"] <-- 注意, 就算只剩一個, 它仍然是一個陣列.
myFun("one", "two");

// a, "one"
// b, "two"
// manyMoreArgs, [] <-- 仍然是一個陣列

參數長度

  • 因為 theArgs 是一個陣列, 項目的總數可以從 length 屬性得到:
function fun1(...theArgs) {
  console.log(theArgs.length);
}

fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3

組合使用 rest 參數 與 一般參數

  • 以下範例用於收集第一個參數之後的所有參數. 每個參數都與第一個參數相乘, 再回傳陣列.
function multiply(multiplier, ...theArgs) {
  return theArgs.map((element) => {
    return multiplier * element;
  });
}

let arr = multiply(2, 15, 25, 42);
console.log(arr); // [30, 50, 84]

rest 參數是真的陣列; arguments 物件不是

function sortRestArgs(...theArgs) {
  let sortedArgs = theArgs.sort();
  return sortedArgs;
}

console.log(sortRestArgs(5, 3, 7, 1)); // 1, 3, 5, 7

function sortArguments() {
  let sortedArgs = arguments.sort();
  return sortedArgs;
}

console.log(sortArguments(5, 3, 7, 1));
// 拋出一個 TypeError (arguments.sort 不是一個函式)
  • 要用 Array 的方法, 必須先轉成真的陣列.
function sortArguments() {
  let args = Array.from(arguments);
  let sortedArgs = args.sort();
  return sortedArgs;
}
console.log(sortArguments(5, 3, 7, 1)); // 1, 3, 5, 7

瀏覽器相容

  • 只有 IE 不支援, 其他瀏覽器都完全支援

ChaoLiou avatar Jan 27 '21 04:01 ChaoLiou