JavaScript 可变数量的函数参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2141520/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 22:55:39  来源:igfitidea点击:

JavaScript variable number of arguments to function

javascriptfunctionargumentsargument-passing

提问by Timo

Is there a way to allow "unlimited" vars for a function in JavaScript?

有没有办法允许 JavaScript 中的函数的“无限”变量?

Example:

例子:

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

回答by roufamatic

Sure, just use the argumentsobject.

当然,只需使用arguments对象。

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

回答by Ramast

In (most) recent browsers, you can accept variable number of arguments with this syntax:

在(大多数)最近的浏览器中,您可以使用以下语法接受可变数量的参数:

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

Here's a small example:

这是一个小例子:

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

Documentation and more examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters

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

回答by Ken

Another option is to pass in your arguments in a context object.

另一种选择是在上下文对象中传递参数。

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

and use it like this

并像这样使用它

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

This has the advantage that you can add as many named arguments as you want, and the function can use them (or not) as it sees fit.

这样做的好处是您可以根据需要添加任意数量的命名参数,并且函数可以根据需要使用(或不使用)它们。

回答by mbeasley

I agree with Ken's answer as being the most dynamic and I like to take it a step further. If it's a function that you call multiple times with different arguments - I use Ken's design but then add default values:

我同意 Ken 的回答是最有活力的,我喜欢更进一步。如果它是一个使用不同参数多次调用的函数 - 我使用 Ken 的设计,然后添加默认值:

function load(context) {

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

    var context = extend(defaults, context);

    // do stuff
}

This way, if you have many parameters but don't necessarily need to set them with each call to the function, you can simply specify the non-defaults. For the extend method, you can use jQuery's extend method ($.extend()), craft your own or use the following:

这样,如果您有许多参数但不一定需要在每次调用函数时都设置它们,您可以简单地指定非默认值。对于扩展方法,您可以使用 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];
}

This will merge the context object with the defaults and fill in any undefined values in your object with the defaults.

这会将上下文对象与默认值合并,并使用默认值填充对象中的任何未定义值。

回答by Canavar

Yes, just like this :

是的,就像这样:

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

load(1,2);

回答by Nicola Pedretti

It is preferable to use rest parameter syntax as Ramast pointed out.

正如 Ramast 指出的那样,最好使用 rest 参数语法。

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

I just want to add some nice property of the ...args argument

我只想添加 ...args 参数的一些不错的属性

  1. It is an array, and not an object like arguments. This allows you to apply functions like map or sort directly.
  2. It does not include all parameters but only the one passed from it on. E.g. function (a, b, ...args) in this case args contains argument 3 to arguments.length
  1. 它是一个数组,而不是像参数这样的对象。这允许您直接应用 map 或 sort 等功能。
  2. 它不包括所有参数,而只包括从它传递过来的参数。例如 function (a, b, ...args) 在这种情况下 args 包含参数 3 到arguments.length

回答by Peter Tseng

As mentioned already, you can use the argumentsobject to retrieve a variable number of function parameters.

如前所述,您可以使用该arguments对象来检索可变数量的函数参数。

If you want to call another function with the same arguments, use apply. You can even add or remove arguments by converting argumentsto an array. For example, this function inserts some text before logging to console:

如果要调用具有相同参数的另一个函数,请使用apply. 您甚至可以通过转换arguments为数组来添加或删除参数。例如,此函数在登录到控制台之前插入一些文本:

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

回答by mcurland

Although I generally agree that the named arguments approach is useful and flexible (unless you care about the order, in which case arguments is easiest), I do have concerns about the cost of the mbeasley approach (using defaults and extends). This is an extreme amount of cost to take for pulling default values. First, the defaults are defined inside the function, so they are repopulated on every call. Second, you can easily read out the named values and set the defaults at the same time using ||. There is no need to create and merge yet another new object to get this information.

尽管我普遍同意命名参数方法有用且灵活(除非您关心顺序,在这种情况下参数是最简单的),但我确实担心 mbeasley 方法(使用默认值和扩展)的成本。这是提取默认值所需的极大成本。首先,默认值是在函数内部定义的,因此在每次调用时都会重新填充它们。其次,您可以使用 || 轻松读出命名值并同时设置默认值。无需创建和合并另一个新对象来获取此信息。

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

   // do stuff
}

This is roughly the same amount of code (maybe slightly more), but should be a fraction of the runtime cost.

这与代码量大致相同(可能略多),但应该是运行时成本的一小部分。

回答by Brian Ellis

While @roufamatic did show use of the arguments keyword and @Ken showed a great example of an object for usage I feel neither truly addressed what is going on in this instance and may confuse future readers or instill a bad practice as not explicitly stating a function/method is intended to take a variable amount of arguments/parameters.

虽然@roufamatic 确实展示了arguments 关键字的使用,而@Ken 展示了一个很好的使用对象示例,但我觉得这两个例子都没有真正解决这个例子中发生的事情,并且可能会让未来的读者感到困惑,或者灌输一种不好的做法,因为没有明确说明一个函数/method 旨在采用可变数量的参数/参数。

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

When another developer is looking through your code is it very easy to assume this function does not take parameters. Especially if that developer is not privy to the argumentskeyword. Because of this it is a good idea to follow a style guideline and be consistent. I will be using Google's for all examples.

当其他开发人员查看您的代码时,很容易假设此函数不带参数。特别是如果该开发人员不知道参数关键字。因此,遵循风格指南并保持一致是个好主意。我将在所有示例中使用 Google 的。

Let's explicitly state the same function has variable parameters:

让我们明确声明相同的函数具有可变参数:

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

Object parameter VS var_args

对象参数 VS var_args

There may be times when an object is needed as it is the only approved and considered best practice method of an data map. Associative arrays are frowned upon and discouraged.

有时可能需要一个对象,因为它是唯一被批准和考虑的数据映射最佳实践方法。关联数组是不受欢迎和不鼓励的。

SIDENOTE:The arguments keyword actually returns back an object using numbers as the key. The prototypal inheritance is also the object family. See end of answer for proper array usage in JS

旁注:arguments 关键字实际上返回一个使用数字作为键的对象。原型继承也是对象家族。有关 JS 中正确使用数组的信息,请参阅答案结尾

In this case we can explicitly state this also. Note: this naming convention is not provided by Google but is an example of explicit declaration of a param's type. This is important if you are looking to create a more strict typed pattern in your code.

在这种情况下,我们也可以明确说明这一点。注意:此命名约定不是由 Google 提供的,而是显式声明参数类型的示例。如果您希望在代码中创建更严格的类型化模式,这一点很重要。

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

Which one to choose?

选择哪一个?

This depends on your function's and program's needs. If for instance you are simply looking to return a value base on an iterative process across all arguments passed then most certainly stick with the argumentskeyword. If you need definition to your arguments and mapping of the data then the object method is the way to go. Let's look at two examples and then we're done!

这取决于您的函数和程序的需要。例如,如果您只是想根据传递的所有参数的迭代过程返回一个值,那么肯定会坚持使用arguments关键字。如果您需要定义参数和映射数据,那么对象方法就是您要走的路。让我们看两个例子,然后我们就完成了!

Arguments usage

参数用法

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

Object usage

对象使用

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

Accessing an array instead of an object ("...args" The rest parameter)

访问数组而不是对象("...args" 其余参数)

As mentioned up top of the answer the argumentskeyword actually returns an object. Because of this any method you want to use for an array will have to be called. An example of this:

正如在答案顶部提到的,arguments关键字实际上返回一个对象。因此,您要用于数组的任何方法都必须被调用。一个例子:

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

To avoid this use the rest parameter:

为避免这种情况,请使用 rest 参数:

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

回答by nickytonline

Use the argumentsobject when inside the function to have access to all arguments passed in.

arguments在函数内部使用该对象可以访问传入的所有参数。