Solución:
El modismo más cercano a *args
sería
function func (a, b /*, *args*/) {
var star_args = Array.prototype.slice.call (arguments, func.length);
/* now star_args[0] is the first undeclared argument */
}
aprovechando el hecho de que Function.length
es el número de argumentos dados en la definición de la función.
Podrías empaquetar esto en una pequeña rutina de ayuda como
function get_star_args (func, args) {
return Array.prototype.slice.call (args, func.length);
}
y luego haz
function func (a, b /*, *args*/) {
var star_args = get_star_args (func, arguments);
/* now star_args[0] is the first undeclared argument */
}
Si está de humor para el azúcar sintáctico, escriba una función que transforme una función en otra que se llame con argumentos obligatorios y opcionales, y pase los argumentos requeridos junto con cualquier argumento opcional adicional como una matriz en la posición final:
function argsify(fn){
return function(){
var args_in = Array.prototype.slice.call (arguments); //args called with
var required = args_in.slice (0,fn.length-1); //take first n
var optional = args_in.slice (fn.length-1); //take remaining optional
var args_out = required; //args to call with
args_out.push (optional); //with optionals as array
return fn.apply (0, args_out);
};
}
Use esto de la siguiente manera:
// original function
function myfunc (a, b, star_args) {
console.log (a, b, star_args[0]); // will display 1, 2, 3
}
// argsify it
var argsified_myfunc = argsify (myfunc);
// call argsified function
argsified_myfunc (1, 2, 3);
Por otra parte, podría omitir todo este galimatías si está dispuesto a pedirle a la persona que llama que pase los argumentos opcionales como una matriz para comenzar:
myfunc (1, 2, [3]);
Realmente no existe una solución análoga para **kwargs
, ya que JS no tiene argumentos de palabras clave. En su lugar, simplemente pídale a la persona que llama que pase los argumentos opcionales como un objeto:
function myfunc (a, b, starstar_kwargs) {
console.log (a, b, starstar_kwargs.x);
}
myfunc (1, 2, {x:3});
Actualización de ES6
Para completar, permítanme agregar que ES6 resuelve este problema con la función de parámetro de descanso. Ver Javascript – ‘…’ significado
ES6 agregó un operador de propagación a JavaScript.
function choose(choice, ...availableChoices) {
return availableChoices[choice];
}
choose(2, "one", "two", "three", "four");
// returns "three"
Encontré una buena solución aquí: http://readystate4.com/2008/08/17/javascript-argument-unpacking-converting-an-array-into-a-list-of-arguments/
Básicamente, usa function.apply(obj, [args])
en lugar de function.call
. apply toma una matriz como segundo argumento y la ‘splats’ por usted.