JavaScript变量数量的参数函数

是否有一种方法允许“无限”变量的函数在JavaScript?

例子:

load(var1, var2, var3, var4, var5, etc...)
load(var1)
457004 次浏览

当然,只需使用arguments对象。

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

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

是的,就像这样:

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


load(1,2);

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

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

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

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

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


// do stuff
}

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

请注意,按照Ken的建议传递带有命名属性的Object会增加分配和释放临时对象到每次调用的成本。通过值或引用传递普通参数通常是最有效的。对于许多应用程序,虽然性能不是关键,但对于某些应用程序,它可能是关键。

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

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

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

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

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

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

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

我只是想添加一些很好的属性。args参数

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

虽然@roufamatic确实展示了arguments关键字的使用,@Ken展示了一个很好的对象使用示例,但我觉得两者都没有真正解决这个实例中发生的事情,并且可能会使未来的读者感到困惑,或者逐渐形成一个坏习惯,因为没有显式地说明一个函数/方法的目的是采用可变数量的参数/参数。

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

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

让我们显式地声明同一个函数有变量形参:

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

对象参数VS var_args

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

arguments关键字实际上返回一个以数字为键的对象。原型继承也是对象族。在JS中正确使用数组,请参阅答案末尾

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

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

选择哪一个?

这取决于函数和程序的需要。例如,如果您只是希望在传递的所有参数的迭代过程中返回一个值,那么最肯定的是使用参数关键字。如果你需要定义你的参数和数据映射,那么对象方法是正确的选择。让我们看两个例子,然后我们就完成了!

参数的使用

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“其余参数)

正如前面提到的,参数关键字实际上返回一个对象。正因为如此,你想要为数组使用的任何方法都必须被调用。举个例子:

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

使用数组,然后你可以使用你需要的参数。例如,计算数组中元素个数的平均值:

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