簡體   English   中英

JavaScript 可變數量的函數參數

[英]JavaScript variable number of arguments to function

有沒有辦法允許 JavaScript 中的函數的“無限”變量?

例子:

load(var1, var2, var3, var4, var5, etc...)
load(var1)

當然,只需使用arguments對象。

function foo() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}

在(大多數)最近的瀏覽器中,您可以使用以下語法接受可變數量的參數:

function my_log(...args) {
     // args is an Array
     console.log(args);
     // You can pass this array as parameters to another function
     console.log(...args);
}

這是一個小例子:

function foo(x, ...args) {
  console.log(x, args, ...args, arguments);
}

foo('a', 'b', 'c', z='d')

=>

a
Array(3) [ "b", "c", "d" ]
b c d
Arguments
​    0: "a"
    ​1: "b"
    ​2: "c"
    ​3: "d"
    ​length: 4

此處的文檔和更多示例: https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters

另一種選擇是在上下文對象中傳遞參數。

function load(context)
{
    // do whatever with context.name, context.address, etc
}

並像這樣使用它

load({name:'Ken',address:'secret',unused:true})

這樣做的好處是您可以根據需要添加任意數量的命名參數,並且函數可以根據需要使用(或不使用)它們。

我同意 Ken 的回答是最有活力的,我喜歡更進一步。 如果它是一個使用不同參數多次調用的函數 - 我使用 Ken 的設計,然后添加默認值:

function load(context) {

    var defaults = {
        parameter1: defaultValue1,
        parameter2: defaultValue2,
        ...
    };

    var context = extend(defaults, context);

    // do stuff
}

這樣,如果您有許多參數但不一定需要在每次調用函數時都設置它們,您可以簡單地指定非默認值。 對於擴展方法,您可以使用 jQuery 的擴展方法( $.extend() ),自己制作或使用以下方法:

function extend() {
    for (var i = 1; i < arguments.length; i++)
        for (var key in arguments[i])
            if (arguments[i].hasOwnProperty(key))
                arguments[0][key] = arguments[i][key];
    return arguments[0];
}

這會將上下文對象與默認值合並,並使用默認值填充對象中的任何未定義值。

正如 Ramast 指出的那樣,最好使用 rest 參數語法。

function (a, b, ...args) {}

我只想添加 ...args 參數的一些不錯的屬性

  1. 它是一個數組,而不是像參數這樣的對象。 這允許您直接應用 map 或 sort 等功能。
  2. 它不包括所有參數,而只包括從它傳遞過來的參數。 例如 function (a, b, ...args) 在這種情況下 args 包含參數 3 到arguments.length

是的,就像這樣:

function load()
{
  var var0 = arguments[0];
  var var1 = arguments[1];
}

load(1,2);

如前所述,您可以使用arguments對象來檢索可變數量的函數參數。

如果要使用相同的參數調用另一個函數,請使用apply 您甚至可以通過將arguments轉換為數組來添加或刪除參數。 例如,此函數在登錄到控制台之前插入一些文本:

log() {
    let args = Array.prototype.slice.call(arguments);
    args = ['MyObjectName', this.id_].concat(args);
    console.log.apply(console, args);
}

盡管我普遍同意命名參數方法有用且靈活(除非您關心順序,在這種情況下參數是最簡單的),但我確實擔心 mbeasley 方法(使用默認值和擴展)的成本。 這是提取默認值所需的極大成本。 首先,默認值是在函數內部定義的,因此在每次調用時都會重新填充它們。 其次,您可以使用 || 輕松讀出命名值並同時設置默認值。 無需創建和合並另一個新對象來獲取此信息。

function load(context) {
   var parameter1 = context.parameter1 || defaultValue1,
       parameter2 = context.parameter2 || defaultValue2;

   // do stuff
}

這與代碼量大致相同(可能略多),但應該是運行時成本的一小部分。

雖然@roufamatic 確實展示了arguments 關鍵字的使用,而@Ken 展示了一個很好的使用對象示例,但我覺得這兩個例子都沒有真正解決這個例子中發生的事情,並且可能會讓未來的讀者感到困惑,或者灌輸一種不好的做法,因為沒有明確說明一個函數/method 旨在采用可變數量的參數/參數。

function varyArg () {
    return arguments[0] + arguments[1];
}

當其他開發人員查看您的代碼時,很容易假設此函數不帶參數。 特別是如果該開發人員不知道參數關鍵字。 因此,遵循風格指南並保持一致是個好主意。 我將在所有示例中使用 Google 的。

讓我們明確聲明相同的函數具有可變參數:

function varyArg (var_args) {
    return arguments[0] + arguments[1];
}

對象參數 VS var_args

有時可能需要一個對象,因為它是唯一被批准和考慮的數據映射最佳實踐方法。 關聯數組是不受歡迎和不鼓勵的。

旁注: arguments 關鍵字實際上返回一個使用數字作為鍵的對象。 原型繼承也是對象家族。 有關 JS 中正確使用數組的信息,請參閱答案結尾

在這種情況下,我們也可以明確說明這一點。 注意:此命名約定不是由 Google 提供的,而是顯式聲明參數類型的示例。 如果您希望在代碼中創建更嚴格的類型化模式,這一點很重要。

function varyArg (args_obj) {
    return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});

選擇哪一個?

這取決於您的函數和程序的需要。 例如,如果您只是想根據傳遞的所有參數的迭代過程返回一個值,那么肯定會堅持使用arguments關鍵字。 如果您需要定義參數和映射數據,那么對象方法就是您要走的路。 讓我們看兩個例子,然后我們就完成了!

參數用法

function sumOfAll (var_args) {
    return arguments.reduce(function(a, b) {
        return a + b;
    }, 0);
}
sumOfAll(1,2,3); // returns 6

對象使用

function myObjArgs(args_obj) {
    // MAKE SURE ARGUMENT IS AN OBJECT OR ELSE RETURN
    if (typeof args_obj !== "object") {
        return "Arguments passed must be in object form!";
    }

    return "Hello "+args_obj.name+" I see you're "+args_obj.age+" years old.";
}
myObjArgs({name: "Brian", age: 31}); // returns 'Hello Brian I see you're 31 years old

訪問數組而不是對象("...args" 其余參數)

正如在答案頂部提到的, arguments關鍵字實際上返回一個對象。 因此,您要用於數組的任何方法都必須被調用。 這方面的一個例子:

Array.prototype.map.call(arguments, function (val, idx, arr) {});

為避免這種情況,請使用 rest 參數:

function varyArgArr (...var_args) {
    return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5

arguments內部使用arguments對象可以訪問傳入的所有參數。

請注意,按照 Ken 的建議傳遞具有命名屬性的對象會增加為每次調用分配和釋放臨時對象的成本。 通過值或引用傳遞普通參數通常是最有效的。 對於許多應用程序,雖然性能並不重要,但對於某些應用程序來說可能是。

使用數組,然后您可以使用您需要的參數數量。 例如,計算數組元素個數的平均值:

function fncAverage(sample) {
    var lenghtSample = sample.length;
    var elementsSum = 0;
    for (var i = 0; i < lenghtSample; i++) {
        elementsSum = Number(elementsSum) + Number(sample[i]);
    }
    average = elementsSum / lenghtSample
    return (average);
}

console.log(fncAverage([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])); // results 5.5

let mySample = [10, 20, 30, 40];
console.log(fncAverage(mySample)); // results 25

//try your own arrays of numbers

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM