JavaScript变量函数的参数数量

Tim*_*imo 510 javascript arguments function argument-passing

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

例:

load(var1, var2, var3, var4, var5, etc...)
load(var1)
Run Code Online (Sandbox Code Playgroud)

rou*_*tic 790

当然,只需使用该arguments对象.

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

  • `arguments`是一个特殊的"类似数组"对象,这意味着它有一个长度,但没有其他数组函数.有关更多信息,请参阅https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments,以及此答案:http://stackoverflow.com/a/13145228/1766230 (23认同)
  • 这个解决方案最适合我.谢谢.有关arguments关键字[HERE]的更多信息(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments). (4认同)
  • 有趣的是,Javascript中的Array方法已经定义为可以处理任何具有`length`属性的对象.这包括`arguments`对象.知道这一点,并且方法`concat`返回*它被调用的'数组'的副本*,我们可以很容易地将`arguments`对象转换为这样的实数数组:`var args = [] .concat.call (参数)`.有些人喜欢使用`Array.prototype.concat.call`,但我喜欢`[]`,它们简短又甜蜜! (4认同)
  • @DavidGatti 从拇指向下的文本中:“这已不推荐作为 Function 的属性。请改用函数中可用的参数对象。” (3认同)
  • **已弃用** 此功能已从 Web 标准中删除。虽然一些浏览器可能仍然支持它,但它正在被删除。尽可能避免使用它并更新现有代码;请参阅本页底部的兼容性表以指导您的决定。请注意,此功能可能随时停止工作。 (2认同)
  • @DavidGatti 看起来使用 `Function.arguments` 已被弃用,但不推荐使用普通的 `arguments` 对象。请参阅 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function 。 (2认同)
  • @YasirJan使用```[... arguments] .join()``` (2认同)

Ram*_*ast 152

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

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

  • 仅供参考,它被称为"其余参数语法":https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters (23认同)
  • +1这是优雅而干净的解决方案.特别适合于将长参数列表传递到另一个函数调用中,并且可能那些变量参数位于任意位置. (4认同)
  • 请记住,根据https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/rest_parameters,IE不支持它。 (3认同)
  • 下表显示了浏览器支持-https://caniuse.com/#feat=rest-parameters (2认同)
  • 值得注意的是,“z='d'”语法不会分配给名为“z”的参数(就像在 Python 中那样),而是传递一个未命名的参数值“d”*并*创建**局部变量** `z` 与 **副作用** 具有相同的值。 (2认同)

Ken*_*Ken 111

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

function load(context)
{
    // do whatever with context.name, context.address, etc
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它

load({name:'Ken',address:'secret',unused:true})
Run Code Online (Sandbox Code Playgroud)

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

  • 当然,在某些情况下这更好.但是,让我们说各个论点并不真正相互关联,或者都应该具有相同的意义(如数组元素).那么OP的方式是最好的. (9认同)
  • 这会更好,因为它删除了与参数顺序的耦合.松散耦合的接口是良好的标准做法...... (4认同)

mbe*_*ley 45

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

function load(context) {

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

    var context = extend(defaults, context);

    // do stuff
}
Run Code Online (Sandbox Code Playgroud)

这样,如果您有许多参数但不一定需要在每次调用函数时设置它们,您只需指定非默认值即可.对于extend方法,您可以使用jQuery的extend方法($.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];
}
Run Code Online (Sandbox Code Playgroud)

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

  • +1.好戏.节省了大量的锅炉板以定义每个参数,默认或其他. (3认同)

Can*_*var 18

是的,就像这样:

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

load(1,2);
Run Code Online (Sandbox Code Playgroud)


Nic*_*tti 16

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

function (a, b, ...args) {}
Run Code Online (Sandbox Code Playgroud)

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

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


Pet*_*eng 13

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

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

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


mcu*_*and 8

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

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

   // do stuff
}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果任何参数接受/期望'0',这将失败. (2认同)

Bri*_*lis 7

虽然@roufamatic确实显示了arguments关键字的使用,而@Ken显示了一个使用对象的一个​​很好的例子,但我觉得它并没有真正解决这个实例中发生的事情,可能会混淆未来的读者或灌输一个不好的做法,因为没有明确说明一个函数/ method旨在获取可变数量的参数/参数.

function varyArg () {
    return arguments[0] + arguments[1];
}
Run Code Online (Sandbox Code Playgroud)

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

让我们明确说明同一个函数有变量参数:

function varyArg (var_args) {
    return arguments[0] + arguments[1];
}
Run Code Online (Sandbox Code Playgroud)

对象参数VS var_args

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

SIDENOTE: arguments关键字实际上使用数字作为键返回一个对象.原型继承也是对象家族.请参阅答案的结尾以了解JS中正确的数组使用情况

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

function varyArg (args_obj) {
    return args_obj.name+" "+args_obj.weight;
}
varyArg({name: "Brian", weight: 150});
Run Code Online (Sandbox Code Playgroud)

哪一个选择?

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

参数用法

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

对象用法

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
Run Code Online (Sandbox Code Playgroud)

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

如上所述,arguments关键字实际上返回一个对象.因此,必须调用要用于数组的任何方法.一个例子:

Array.prototype.map.call(arguments, function (val, idx, arr) {});
Run Code Online (Sandbox Code Playgroud)

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

function varyArgArr (...var_args) {
    return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
Run Code Online (Sandbox Code Playgroud)


小智 6

请注意,按照 Ken 的建议传递具有命名属性的对象会增加为每次调用分配和释放临时对象的成本。通过值或引用传递普通参数通常是最有效的。对于许多应用程序来说,性能并不重要,但对于某些应用程序来说,性能可能很重要。


nic*_*ine 5

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