JavaScript variable número de argumentos a funcionar


¿Hay alguna forma de permitir vars "ilimitados" para una función en JavaScript?

Ejemplo:

load(var1, var2, var3, var4, var5, etc...)
load(var1)
Author: bluish, 2010-01-26

11 answers

Claro, solo usa el objeto arguments.

function foo() {
  for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
  }
}
 708
Author: roufamatic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-26 17:04:54

Otra opción es pasar los argumentos en un objeto context.

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

Y usarlo así

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

Esto tiene la ventaja de que puede agregar tantos argumentos con nombre como desee, y la función puede usarlos (o no) como considere oportuno.

 103
Author: Ken,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-26 18:34:14

En navegadores recientes, puede aceptar un número variable de argumentos con esta sintaxis:

function my_log(...args) {
     //args is an Array
     console.log(args);
     //You can pass this array as parameters to another function
     console.log(...args);
}
 81
Author: Ramast,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-20 04:46:27

Estoy de acuerdo con la respuesta de Ken como la más dinámica y me gusta ir un paso más allá. Si es una función a la que llamas varias veces con diferentes argumentos, utilizo el diseño de Ken pero luego añado valores predeterminados:

function load(context) {

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

    var context = extend(defaults, context);

    // do stuff
}

De esta manera, si tiene muchos parámetros pero no necesariamente necesita configurarlos con cada llamada a la función, simplemente puede especificar los que no son predeterminados. Para el método extend, puede usar el método extend de jQuery ($.extend()), crear el suyo propio o usar el siguiente:

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

Esto fusionará el objeto de contexto con los valores predeterminados y completará cualquier valor indefinido en su objeto con los valores predeterminados.

 45
Author: mbeasley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-23 14:11:39

Sí, así:

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

load(1,2);
 17
Author: Canavar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-26 18:08:12

Como ya se mencionó, puede usar el objeto arguments para recuperar un número variable de parámetros de función.

Si desea llamar a otra función con los mismos argumentos, utilice apply. Incluso puede agregar o eliminar argumentos convirtiendo arguments a una matriz. Por ejemplo, esta función inserta algo de texto antes de iniciar sesión en la consola:

log() {
    let args = Array.prototype.slice.call(arguments);
    args = ['MyObjectName', this.id_].concat(args);
    console.log.apply(console, args);
}
 9
Author: Peter Tseng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-12 02:27:41

Aunque generalmente estoy de acuerdo en que el enfoque de argumentos con nombre es útil y flexible (a menos que le importe el orden, en cuyo caso los argumentos son más fáciles), me preocupa el costo del enfoque mbeasley (usando valores predeterminados y extensiones). Esta es una cantidad extrema de costo para tirar de los valores predeterminados. En primer lugar, los valores predeterminados se definen dentro de la función, por lo que se repoblan en cada llamada. En segundo lugar, puede leer fácilmente los valores nombrados y establecer los valores predeterminados al mismo tiempo usando|/. No hay necesidad de crear y combinar otro objeto nuevo para obtener esta información.

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

   // do stuff
}

Esto es aproximadamente la misma cantidad de código (quizás un poco más), pero debería ser una fracción del costo de tiempo de ejecución.

 8
Author: mcurland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-07 21:59:37

Es preferible usar la sintaxis del parámetro rest como Ramast señaló.

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

Solo quiero añadir alguna propiedad agradable de la ...argumento args

  1. es una matriz, y no un objeto como argumentos. Esto le permite aplicar funciones como map o sort directamente.
  2. No incluye todos los parámetros, sino solo el que se pasa a partir de él. Por ejemplo, función (a, b,...args) en este caso args contiene argumento 3 a argumentos.longitud
 8
Author: Nicola Pedretti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-02 15:40:32

Use el objeto arguments cuando esté dentro de la función para tener acceso a todos los argumentos pasados.

 5
Author: nickytonline,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-08 09:51:23

Mientras que @roufamatic mostró el uso de la palabra clave arguments y @Ken mostró un gran ejemplo de un objeto para su uso, siento que ni realmente aborda lo que está sucediendo en este caso y puede confundir a futuros lectores o inculcar una mala práctica ya que no indica explícitamente que una función/método está destinado a tomar una cantidad variable de argumentos/parámetros.

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

Cuando otro desarrollador está mirando a través de su código es muy fácil asumir que esta función no toma parámetros. Especialmente si ese desarrollador no está al tanto de la palabra clave arguments. Debido a esto, es una buena idea seguir una guía de estilo y ser consistente. Usaré Google para todos los ejemplos.

Digamos explícitamente que la misma función tiene parámetros variables:

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

Parámetro de objeto VS var_args

Puede haber ocasiones en las que se necesite un objeto, ya que es el único método de mejores prácticas aprobado y considerado de un mapa de datos. Los arrays asociativos están mal vistos y desanimar.

NOTA LATERAL: La palabra clave arguments realmente devuelve un objeto usando números como clave. La herencia prototípica es también la familia de objetos. Ver fin de respuesta para el uso adecuado de la matriz en JS

En este caso podemos declarar explícitamente esto también. Nota: esta convención de nomenclatura no es proporcionada por Google, pero es un ejemplo de declaración explícita del tipo param. Esto es importante si está buscando crear un patrón escrito más estricto en su codificar.

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

Cuál elegir?

Esto depende de las necesidades de su función y programa. Si, por ejemplo, simplemente está buscando devolver una base de valores en un proceso iterativo a través de todos los argumentos pasados, entonces sin duda se adhieren a la palabra clave arguments. Si necesita definir sus argumentos y mapear los datos, entonces el método object es el camino a seguir. Echemos un vistazo a dos ejemplos y luego hemos terminado!

Argumentos uso

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

Uso del objeto

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

Accediendo a un array en lugar de a un objeto ("...args" El parámetro rest)

Como se mencionó arriba de la respuesta, la palabra clave arguments realmente devuelve un objeto. Debido a esto, cualquier método que desee usar para una matriz tendrá que ser llamado. Un ejemplo de esto:

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

Para evitar esto use el parámetro rest:

function varyArgArr (...var_args) {
    return var_args.sort();
}
varyArgArr(5,1,3); // returns 1, 3, 5
 5
Author: Brian Ellis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-24 04:29:00

Tenga en cuenta que pasar un Objeto con propiedades nombradas como Ken sugirió agrega el costo de asignar y liberar el objeto temporal a cada llamada. Pasar argumentos normales por valor o referencia generalmente será el más eficiente. Para muchas aplicaciones, aunque el rendimiento no es crítico, pero para algunas puede serlo.

 2
Author: phbcanada,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-06 20:25:50