JavaScript可变参数数量的函数

有没有一种方法来允许JavaScript的函数“无限”的variables?

例:

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

当然,只需使用arguments对象。

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

另一个select是传递你的参数在一个上下文对象中。

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

像这样使用它

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

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

我同意肯的回答是最有活力的,我想更进一步。 如果这是一个函数,你用不同的参数多次调用 – 我使用Ken的devise,但添加默认值:

 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]; } 

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

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

 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 load() { var var0 = arguments[0]; var var1 = arguments[1]; } load(1,2); 

虽然我一般都认为命名参数的方法是有用和灵活的(除非你关心的顺序,在这种情况下参数是最简单的),我确实担心mbeasley方法的成本(使用默认值和扩展)。 这是拉取默认值所需的极端成本。 首先,默认值是在函数内部定义的,所以在每次调用时都会重新填充它们。 其次,您可以轻松地读出命名值并使用||同时设置默认值。 没有必要创build和合并另一个新的对象来获取这些信息。

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

这个代码的数量大致相同(也许稍微多一些),但是应该是运行成本的一小部分。

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

如果你想用相同的参数调用另一个函数,使用apply 。 您甚至可以通过将arguments转换为数组来添加或删除参数。 例如,这个函数在login到控制台之前插入一些文本:

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

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

最好使用Ramast指出的rest参数语法。

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

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

  1. 它是一个数组,而不是像参数一样的对象。 这使您可以直接应用地图或sorting等function。
  2. 它不包括所有参数,但只包含从它传递的参数。 例如,在这种情况下,函数(a,b,… args)args包含参数3到arguments.length

虽然@roufamatic确实显示了关键字的使用,而@Ken展示了一个很好的使用对象的例子,我觉得这个例子并没有真正解决这个问题,并且可能会混淆未来的读者,或者灌输一个不好的做法,因为没有明确的说明函数/方法是为了获取可变数量的参数/参数。

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

当另一个开发人员查看代码时,很容易假设这个函数不带参数。 特别是如果该开发人员不是参与关键字的参考。 正因为如此,遵循风格指引并保持一致是个好主意。 我将使用谷歌的所有例子。

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

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

对象参数VS var_args

有时可能需要一个对象,因为它是数据映射唯一被认可和考虑的最佳实践方法。 联想arrays被压抑和沮丧。

SIDENOTE:参数关键字实际上以数字作为关键字返回一个对象。 原型inheritance也是对象族。 请参阅答案的结尾在JS中正确的数组使用

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

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

哪一个select?

这取决于你的function和程序的需求。 例如,如果您只是希望返回所有传递参数的迭代过程的值基础,那么肯定会使用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) {}); 

为了避免这个使用其余的参数:

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

请注意,如Ken所示,传递具有指定属性的对象会增加为每个调用分配和释放临时对象的成本。 通过价值或引用传递正常参数通常是最有效的。 对于许多应用程序来说,虽然性能并不重要,但对于一些应用程序来说,