Pase un número desconocido de argumentos a la función javascript

84

¿Hay alguna manera de pasar un número desconocido de argumentos como:

var print_names = function(names) {
    foreach(name in names) console.log(name); // something like this
}

print_names('foo', 'bar', 'baz');

Además, ¿cómo obtengo la cantidad de argumentos pasados?

ajsie
fuente
Hasta ahora, la respuesta de la anulación pública es la única que describe cómo pasar un número desconocido de argumentos (en una llamada de función) (usando .apply). Los otros muestran cómo leer un número desconocido de argumentos (desde dentro de la función) (usando arguments).
Ben J

Respuestas:

146

ES3 (o ES5 o Javascript de la vieja escuela)

Puede acceder a los argumentos pasados ​​a cualquier función de JavaScript a través del argumentsobjeto mágico , que se comporta de manera similar a una matriz. El uso de argumentssu función se vería así

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

Es importante tener en cuenta que noarguments es una matriz. MDC tiene buena documentación al respecto: https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Functions#Using_the_arguments_object

Si desea convertirse argumentsen una matriz para poder hacer cosas como .slice(), .push()etc., use algo como esto:

var args = Array.prototype.slice.call(arguments);

ES6 / Mecanografiado

¡Hay una forma mejor! La nueva función de parámetros de descanso te respalda:

var print_names = function(...names) {
    for (let i=0; i<names.length; i++) console.log(names[i]);
}
ShZ
fuente
3
Gracias por una respuesta tan detallada y al mismo tiempo corta + simple :)
Mese
1
La referencia de ES6 a spread syntaxes bastante incorrecta aquí. Ese es un rest parameterejemplo que dio. Buena respuesta, pero confuso porque se hace referencia comospread
Drenai
¡Gracias por tu respuesta! Encontré que este es un artículo útil que explica lo que está sucediendo con Array.prototype.slice.call(arguments): medium.com/@andrewsburke/…
AnnieP
22

ES6 / ES2015

Aproveche la sintaxis del parámetro rest .

function printNames(...names) {
  console.log(`number of arguments: ${names.length}`);
  for (var name of names) {
    console.log(name);
  }
}

printNames('foo', 'bar', 'baz');

Hay tres diferencias principales entre los parámetros rest y el objeto de argumentos:

  • Los parámetros rest son solo aquellos a los que no se les ha dado un nombre separado, mientras que el objeto de argumentos contiene todos los argumentos pasados ​​a la función;
  • el objeto de argumentos no es una matriz real, mientras que los parámetros de resto son instancias de matriz, lo que significa que métodos como sort, map, forEach o pop se pueden aplicar directamente;
  • el objeto de argumentos tiene una funcionalidad adicional específica para sí mismo (como la propiedad callee).
A RationalDev le gusta GoFundMonica
fuente
Esto tiene mucho sentido para el desarrollo web que generalmente usa una sintaxis PHP común.
Dadan
13
var 
print_names = function() {
    console.log.apply( this, arguments );
};

print_names( 1, 2, 3, 4 );
anulación pública
fuente
7
function print_args() {
    for(var i=0; i<arguments.length; i++)
        console.log(arguments[i])
}
Gabi Purcaru
fuente
6

Hay un objeto oculto pasado a cada función en JavaScript llamada arguments.

Solo usaría arguments.lengthpara obtener la cantidad de argumentos pasados ​​a la función.

Para iterar a través de los argumentos, usaría un ciclo:

for(var i = arguments.length; i--) {
   var arg = arguments[i];
}

Tenga en cuenta que argumentsno es una matriz real, por lo que si la necesitara como una matriz, la convertiría así:

var args = Array.prototype.slice.call(arguments);
Jacob Relkin
fuente
3
Nota sólo que no es una matriz "real", es una "matriz-como" objeto (con algunas características especiales), sino usar "métodos de arrays" en él, tendrá que convertirlo, por ejemplo var args = Array.prototype.slice.call(arguments);, var args = Array.apply(null, arguments);, etc. , hay muchas maneras ...
Christian C. Salvadó
4

arguments.length. puede usar un bucle for en él.

(function () {
    for (var a = [], i = arguments.length; i--;) {
        a.push(arguments[i]);
    };
    return a;
})(1, 2, 3, 4, 5, 6, 7, 8)
meder omuraliev
fuente
@meder, me encanta usar funciones anónimas como esa. Buen ejemplo! Además, ¿le faltan un par de punto y coma?
Jacob Relkin
parece funcionar bien como está.
meder omuraliev
@meder, inserción de punto y coma en JavaScript #ftf
Jacob Relkin
@meder, de hecho, solo el punto y coma después del forbloque no es realmente necesario, sin embargo, agregaría uno al final de la última línea.
Christian C. Salvadó
1
@weng, se trata de FunctionExpressionvs FunctionDeclaration, mira este artículo .
Christian C. Salvadó
2

Mucho mejor ahora para ES6

function Example() {
    return {
        arguments: (...args) =>{
            args.map(a => console.log());
        }
    }
}

var exmpl = new Example();
exmpl.arguments(1, 2, 3, 'a', 'b', 'c');

espero que esto ayude

Santiago Posada
fuente
0

Parámetros de descanso en ES6

const example = (...args) => {
  for (arg in args) {
    console.log(arg);
  }
}

Nota: puede pasar parámetros regulares antes que el resto de parámetros

const example = (arg1, ...args) => {
  console.log(arg1);
  for (arg in args) {
    console.log(arg);
  }
}
Kurtis Streutker
fuente
0

Puede usar el operador spread / rest para recopilar sus parámetros en una matriz y luego la lengthde la matriz será el número de parámetros que pasó:

function foo(...names) {
    console.log(names);
    return names;
}

console.log(foo(1, 2, 3, 4).length);

Usando BabelJS convertí la función a JS de la vieja escuela:

"use strict";

function foo() {
  for (var _len = arguments.length, names = new Array(_len), _key = 0; _key < _len; _key++) {
    names[_key] = arguments[_key];
  }

  console.log(names);
  return names;
}
Lajos Arpad
fuente
0

Puede crear una función utilizando el operador de extensión / reposo y, a partir de ahí, logró su objetivo. Por favor, eche un vistazo al fragmento a continuación.

const print_names = (...args) => args.forEach(x => console.log(x));
mabulu
fuente
0

let x = function(){
  return [].slice.call(arguments);
};

console.log(x('a','b','c','d'));

Sekhar552
fuente
-4

Me gusta hacer esto:

Esto no ayudará si no conoce la cantidad de argumentos, pero es útil si no desea recordar el orden de los mismos.

/**
 *  @param  params.one        A test parameter
 *  @param  params.two        Another one  
 **/
function test(params) {

    var one = params.one;
    if(typeof(one) == 'undefined') {
        throw new Error('params.one is undefined');
    }

    var two = params.two;
    if(typeof(two) == 'undefined') {
        throw new Error('params.two is undefined');
    }
}
Colin Sullivan
fuente
1
La pregunta se refería a un número desconocido de argumentos.
Diseño de Adrian