188

是否可以从数组向 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 并且能够接受 varargs 并发送它们是一个很棒的模式。例如

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 中发送一个数组作为参数数组处理?

4

12 回答 12

238

更新:从 ES6 开始,您可以在调用函数时简单地使用扩展语法:

func(...arr);

由于 ES6 也如果您希望将参数视为数组,您还可以在参数列表中使用扩展语法,例如:

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);

如今,我只建议apply仅在需要从数组中传递任意数量的参数设置this值时才使用。applytake 是this作为第一个参数的值,将在函数调用时使用,如果我们null在非严格代码中使用,this关键字将引用内部的全局对象(窗口)func,在严格模式下,当显式使用 'use strict ' 或在 ES 模块中,null将被使用。

另请注意,该arguments对象并不是真正的数组,您可以通过以下方式对其进行转换:

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

在 ES6 中:

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

arguments但是由于扩展语法,您现在很少直接使用该对象。

于 2009-12-24T17:08:20.490 回答
77

实际上,您可以将任意数量的值传递给任何 javascript 函数。显式命名的参数将获得前几个值,但所有参数都将存储在参数数组中。

要以“解包”形式传递参数数组,您可以使用 apply,如下所示(cf 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);
于 2009-12-24T17:08:59.067 回答
23

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');

请注意传播的 awkard 语法。尚不支持sprintf('The %s %s fox jumps over the %s dog.', ...arr);通常的语法 of 。您可以在此处找到 ES6 兼容性表

还要注意使用for...of,另一个 ES6 添加。使用for...in数组是一个坏主意

于 2013-09-07T11:16:35.050 回答
9

从 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 */

varargsANSI C 为( ...)提供了便利,并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

我更喜欢传播运算符。它是干净的和自我记录的。

于 2017-05-27T16:30:42.340 回答
8

apply函数有两个参数;对象this将被绑定到,参数将用数组表示。

some_func = function (a, b) { return b }
some_func.apply(obj, ["arguments", "are", "here"])
// "are"
于 2009-12-24T17:11:20.077 回答
5

它被称为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); 
于 2009-12-24T17:17:46.287 回答
4

使用 ES6,您可以将剩余参数用于varagrs. 这需要参数列表并将其转换为数组。

function logArgs(...args) {
    console.log(args.length)
    for(let arg of args) {
        console.log(arg)
    }
}
于 2018-08-21T23:10:51.500 回答
2
(function(window) {
  var proxied = window.alert;
  window.alert = function() {
    return proxied.apply(window, arguments);
  };
}(this));

alert(13, 37);
于 2013-10-25T10:01:58.820 回答
2

这是一个示例程序,用于计算变量参数和整数数组的整数总和。希望这可以帮助。

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);
于 2015-02-08T16:48:18.647 回答
1

对于那些从将可变数量的参数从一个函数传递到另一个函数(不应标记为此问题的重复)重定向到此处的人:

如果您尝试将可变数量的参数从一个函数传递给另一个函数,那么从 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 试试看

于 2013-07-31T14:29:33.180 回答
0

你想让你的函数对数组参数或变量参数做出反应吗?如果是后者,请尝试:

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);
  }
};
于 2019-01-05T01:26:58.327 回答
0

是的,您可以传递变量号。函数的参数。您可以使用apply来实现这一点。

例如:

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

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

applyTest.apply(null,arr);
于 2017-05-29T04:18:05.937 回答