web-dev-qa-db-fra.com

Opérateurs Splat en JavaScript, équivalent à * args et ** kwargs en Python?

J'utilise Python beaucoup, et j'apprends rapidement JavaScript en ce moment (ou devrais-je dire réapprentissage). Donc, je voulais demander, quel est l'équivalent de *args et **kwargs en JavaScript?

64
Games Brainiac

L'idiome le plus proche pour *args serait

function func (a, b /*, *args*/) {
    var star_args = Array.prototype.slice.call (arguments, func.length);
    /* now star_args[0] is the first undeclared argument */
}

profitant du fait que Function.length est le nombre d'arguments donnés dans la définition de la fonction.

Vous pouvez emballer cela dans une petite routine d'aide comme

function get_star_args (func, args) {
    return Array.prototype.slice.call (args, func.length);
}

puis faire

function func (a, b /*, *args*/) {
    var star_args = get_star_args (func, arguments);
    /* now star_args[0] is the first undeclared argument */
}

Si vous êtes d'humeur pour le sucre syntaxique, écrivez une fonction qui transforme une fonction en une autre qui est appelée avec les arguments obligatoires et facultatifs, et transmet les arguments requis, avec tous les arguments facultatifs supplémentaires sous forme de tableau en position finale:

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

Utilisez ceci comme suit:

// 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);

Là encore, vous pouvez simplement ignorer tout ce mumbo jumbo si vous êtes prêt à demander à l'appelant de passer les arguments facultatifs sous forme de tableau pour commencer:

myfunc (1, 2, [3]);

Il n'y a vraiment pas de solution analogue pour **kwargs, car JS n'a pas d'argument de mot clé. Au lieu de cela, demandez simplement à l'appelant de passer les arguments facultatifs en tant qu'objet:

function myfunc (a, b, starstar_kwargs) {
    console.log (a, b, starstar_kwargs.x);
}

myfunc (1, 2, {x:3});

Mise à jour ES6

Pour être complet, permettez-moi d'ajouter que ES6 résout ce problème avec la fonction de paramètre de repos. Voir http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html .

38
user663031

ES6 a ajouté un opérateur d'étalement à JavaScript.

function choose(choice, ...availableChoices) {
    return availableChoices[choice];
}

choose(2, "one", "two", "three", "four");
// returns "three"
27
Helio Santos

J'ai trouvé une bonne solution ici: http://readystate4.com/2008/08/17/javascript-argument-unpacking-converting-an-array-into-a-list-of-arguments/

Fondamentalement, utilisez function.apply(obj, [args]) au lieu de function.call. apply prend un tableau comme 2e argument et le "splat" pour vous.

17
Luke W

L'équivalent le plus proche est le arguments pseudo-tablea .

8
NPE

ECMAScript 6 aura paramètres de repos qui font la même chose que l'opérateur splat.

1
Cameron Martin