簡體   English   中英

是否可以向 JavaScript 函數發送可變數量的參數?

[英]Is it possible to send a variable number of arguments to a JavaScript function?

是否可以從數組向 JavaScript 函數發送可變數量的參數?

var arr = ['a','b','c']

var func = function()
{
    // debug 
    alert(arguments.length);
    //
    for(arg in arguments)
        alert(arg);
}

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'

我最近寫了很多 Python,能夠接受可變參數並發送它們是一個很棒的模式。 例如

def func(*args):
   print len(args)
   for i in args:
       print i

func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(*arr) // prints 4 which is what I want, then 'a','b','c','d'

在 JavaScript 中是否可以發送一個數組作為參數數組?

更新:從 ES6 開始,您可以在調用函數時簡單地使用spread 語法

func(...arr);

由於 ES6 同樣,如果您希望將參數視為數組,您還可以在參數列表中使用 spread 語法,例如:

function func(...args) {
  args.forEach(arg => console.log(arg))
}

const values = ['a', 'b', 'c']
func(...values)
func(1, 2, 3)

並且您可以將它與普通參數結合使用,例如,如果您想分別接收前兩個參數並將其余參數作為數組接收:

function func(first, second, ...theRest) {
  //...
}

也許對你有用,你可以知道一個函數需要多少個參數:

var test = function (one, two, three) {}; 
test.length == 3;

但無論如何你可以傳遞任意數量的參數......

傳播語法比apply更短、更“甜蜜”,如果您不需要在函數調用中設置this值,這就是要走的路。

這是一個應用示例,這是以前的方法:

var arr = ['a','b','c'];

function func() {
  console.log(this); // 'test'
  console.log(arguments.length); // 3

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

};

func.apply('test', arr);

現在,我只建議僅在需要從數組中傳遞任意數量的參數設置this值時才使用apply applythis值作為第一個參數,將在函數調用時使用,如果我們在非嚴格代碼中使用null ,則this關鍵字將引用func內部的全局對象(窗口),在嚴格模式下,當明確使用 'use strict' 或在 ES 模塊中,將使用null

另請注意, arguments對象並不是真正的數組,您可以通過以下方式轉換它:

var argsArray = Array.prototype.slice.call(arguments);

在 ES6 中:

const argsArray = [...arguments] // or Array.from(arguments)

但是由於擴展語法,您現在很少直接使用arguments對象。

實際上,您可以將任意數量的值傳遞給任何 javascript 函數。 顯式命名的參數將獲得前幾個值,但所有參數都將存儲在參數數組中。

要以“解壓”形式傳遞參數數組,您可以使用 apply,如下所示(參見Functional Javascript ):

var otherFunc = function() {
   alert(arguments.length); // Outputs: 10
}

var myFunc = function() {
  alert(arguments.length); // Outputs: 10
  otherFunc.apply(this, arguments);
}
myFunc(1,2,3,4,5,6,7,8,9,10);

splatspread運算符是 ES6 的一部分,ES6 是計划中的 Javascript 的下一個版本。 到目前為止,只有 Firefox 支持它們。 此代碼適用於 FF16+:

var arr = ['quick', 'brown', 'lazy'];

var sprintf = function(str, ...args)
{
    for (arg of args) {
        str = str.replace(/%s/, arg);
    }
    return str;
}

sprintf.apply(null, ['The %s %s fox jumps over the %s dog.', ...arr]);
sprintf('The %s %s fox jumps over the %s dog.', 'slow', 'red', 'sleeping');

請注意傳播的尷尬語法。 sprintf('The %s %s fox jumps over the %s dog.', ...arr);的常用語法尚不支持 您可以在此處找到ES6 兼容性表

還要注意for...of的使用,這是 ES6 的另一個補充。 對數組使用for...in個壞主意

ES2015 有兩種方法。

arguments對象

該對象內置於函數中,它適當地引用了函數的參數。 不過,從技術上講,它不是數組,因此典型的數組操作不適用於它。 建議的方法是使用Array.from或擴展運算符從它創建一個數組。

我已經看到其他答案提到使用slice 不要那樣做。 它會阻止優化(來源: MDN )。

Array.from(arguments)
[...arguments]

但是,我認為arguments是有問題的,因為它隱藏了函數接受的輸入。 一個arguments函數通常是這樣寫的:

function mean(){
    let args = [...arguments];
    return args.reduce((a,b)=>a+b) / args.length;
}

有時,函數頭的編寫方式如下,以類似 C 的方式記錄參數:

function mean(/* ... */){ ... }

但這很少見。

至於為什么會出問題,就拿C來說吧。 C 向后兼容 K&R C 語言的一種古老的 pre-ANSI 方言。 K&R C 允許函數原型具有空參數列表。

int myFunction();
/* This function accepts unspecified parameters */

ANSI C 為varargs ( ... ) 和void提供了一個工具來指定一個空的參數列表。

int myFunction(void);
/* This function accepts no parameters */

許多人不經意地用unspecified參數列表 ( int myfunction(); ) 聲明函數,因為他們希望函數采用零參數。 這在技術上是一個錯誤,因為該函數接受參數。 任意數量。

C 中適當的varargs函數采用以下形式:

int myFunction(int nargs, ...);

JavaScript 確實有類似的東西。

擴展運算符/ 其余參數

實際上,我已經向您展示了價差運算符。

...name

它非常通用,也可以用在函數的參數列表(“其余參數”)中,以記錄良好的方式指定可變參數:

function mean(...args){
    return args.reduce((a,b)=>a+b) / args.length;
}

或者作為 lambda 表達式:

((...args)=>args.reduce((a,b)=>a+b) / args.length)(1,2,3,4,5); // 3

我更喜歡傳播運算符。 它是干凈的和自我記錄的。

apply函數接受兩個參數; this將綁定到的對象,以及用數組表示的參數。

some_func = function (a, b) { return b }
some_func.apply(obj, ["arguments", "are", "here"])
// "are"

它被稱為splat運算符。 你可以在 JavaScript 中使用apply

var arr = ['a','b','c','d'];
var func = function() {
    // debug 
    console.log(arguments.length);
    console.log(arguments);
}
func('a','b','c','d'); // prints 4 which is what I want, then 'a','b','c','d'
func(arr); // prints 1, then 'Array'
func.apply(null, arr); 

使用 ES6,您可以為varagrs使用rest 參數 這需要參數列表並將其轉換為數組。

function logArgs(...args) {
    console.log(args.length)
    for(let arg of args) {
        console.log(arg)
    }
}
(function(window) {
  var proxied = window.alert;
  window.alert = function() {
    return proxied.apply(window, arguments);
  };
}(this));

alert(13, 37);

這是一個用於計算變量參數和整數數組的整數總和的示例程序。 希望這可以幫助。

var CalculateSum = function(){
    calculateSumService.apply( null, arguments );
}

var calculateSumService = function(){
    var sum = 0;

    if( arguments.length === 1){
        var args = arguments[0];

        for(var i = 0;i<args.length; i++){
           sum += args[i]; 
        }
    }else{
        for(var i = 0;i<arguments.length; i++){
           sum += arguments[i]; 
        }        
    }

     alert(sum);

}


//Sample method call

// CalculateSum(10,20,30);         

// CalculateSum([10,20,30,40,50]);

// CalculateSum(10,20);

對於那些誰是從重定向到這里傳遞的參數變量數量從一個功能到另一個(這應該被標記為這個問題的副本):

如果您嘗試將可變數量的參數從一個函數傳遞到另一個函數,從 JavaScript 1.8.5 開始,您可以簡單地在第二個函數上調用apply()並傳入arguments參數:

var caller = function()
{
    callee.apply( null, arguments );
}

var callee = function()
{
    alert( arguments.length );
}

caller( "Hello", "World!", 88 ); // Shows "3".

注意:第一個參數是要使用的this參數。 傳遞null將從全局上下文調用函數,即作為全局函數而不是某個對象的方法。

根據本文檔,ECMAScript 5 規范重新定義了apply()方法以采用任何“通用類數組對象”,而不是嚴格意義上的數組。 因此,您可以直接將arguments列表傳遞給第二個函數。

在 Chrome 28.0、Safari 6.0.5 和 IE 10 中測試。用這個 JSFiddle 試試

是的,您可以傳遞變量號。 函數的參數。 您可以使用apply來實現這一點。

例如:

var arr = ["Hi","How","are","you"];

function applyTest(){
    var arg = arguments.length;
    console.log(arg);
}

applyTest.apply(null,arr);

你想讓你的函數對數組參數或變量參數做出反應嗎? 如果是后者,請嘗試:

var func = function(...rest) {
  alert(rest.length);

  // In JS, don't use for..in with arrays
  // use for..of that consumes array's pre-defined iterator
  // or a more functional approach
  rest.forEach((v) => console.log(v));
};

但是如果你想處理一個數組參數

var fn = function(arr) {
  alert(arr.length);

  for(var i of arr) {
    console.log(i);
  }
};

暫無
暫無

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

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