53 votes

Comment puis-je prédéfinir des arguments dans l'appel de fonction JavaScript? (Application de fonction partielle)

Je suis en train d'écrire une fonction JavaScript qui sera de retour de son premier argument(fonction), avec tout le reste de ses arguments comme préréglage des paramètres à cette fonction.

Donc:

fonction(a, b) {
 document.écrire(a + "" + b);
}

la fonction d'ouvreur(...) {...}

setter(out, "bonjour")("monde");
setter(out, "hello", "world")();

Affiche "hello world" à deux reprises. pour certains, la mise en œuvre de setter

J'ai rencontré un problème avec la manipulation le tableau d'arguments sur mon premier essai, mais il semble qu'il y aurait une meilleure façon de le faire.

97voto

Jason Bunting Points 27534

Tout d'abord, vous avez besoin d'une partielle, il y a une différence entre un partiel et un curry - et c'est tout ce dont vous avez besoin, sans cadre:

function partial(func /*, 0..n args */) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var allArguments = args.concat(Array.prototype.slice.call(arguments));
    return func.apply(this, allArguments);
  };
}

Maintenant, en utilisant votre exemple, vous pouvez faire exactement ce que vous êtes après:

partial(out, "hello")("world");
partial(out, "hello", "world")();

// and here is my own extended example
var sayHelloTo = partial(out, "Hello");
sayHelloTo("World");
sayHelloTo("Alex");

L' partial() fonction peut être utilisée pour mettre en œuvre, mais n'est pas nourrissage. Voici une citation d' un article de blog sur la différence:

Où l'application partielle prend une fonction et de il construit une fonction qui prend moins d'arguments, nourrissage construit des fonctions qui prennent plusieurs arguments par composition de fonctions qui prennent chacun un seul argument.

Espérons que cela aide.

3voto

Peter Bailey Points 62125

Est-ce que javascript au curry est ce que vous cherchez?

2voto

Eugene Lazutkin Points 22414

Si vous utilisez Dojo vous suffit d'appeler dojo.attelage() qui n'est presque exactement ce que vous voulez. Presque, car il peut être utilisé pour emballer le contexte. Mais votre exemple est d'abord:

dojo.hitch(out, "hello")("world");
dojo.hitch(out, "hello", "world")();

Ainsi que:

var A = {
  sep: ", ",
  out: function(a, b){ console.log(a + this.sep + b); }
};

// using functions in context    
dojo.hitch(A, A.out, "hello")("world");
dojo.hitch(A, A.out, "hello", "world")();

// using names in context
dojo.hitch(A, "out", "hello")("world");
dojo.hitch(A, "out", "hello", "world")();

dojo.attelage() est la partie du Dojo de Base, de sorte que dès que vous avez inclus dojo.js il est là pour vous.

Une autre installation est disponible dans les dojox.lang.fonctionnelle.curry module (documenté dans la Fonctionnelle de plaisir en JavaScript avec Dojo — il suffit de regarder sur cette page "curry"). Plus précisément, vous pouvez regarder curry () et partielle().

curry() accumule les arguments (comme dans votre exemple), mais avec une différence: dès que l'arité est convaincu qu'il appelle la fonction retournant une valeur. La mise en œuvre de votre exemple:

df.curry(out)("hello")("world");
df.curry(out)("hello", "world");

Notez que la dernière ligne n'a pas de "()" à la fin — il est appelé automatiquement.

partielle() permet de remplacer des arguments au hasard:

df.partial(out, df.arg, "world")("hello");

0voto

Illandril Points 565

** EDIT: Voir Jason Bunting réponse. Cette réponse montre, en réalité, un sous-par voie d'enchaîner de nombreux appels, pas un seul out-call avec des préréglages pour certains des arguments. Si cette réponse, permet en fait à un problème similaire, vous devriez être sûr de faire usage de les appliquer et de les appeler comme Jason recommande, au lieu de l'obscur moyen d'utiliser eval que je pensais jusqu'. **

Eh bien... votre serviront à l'écriture de "undefined" beaucoup de choses dans cette... mais ce devrait être proche de ce que vous voulez:

function out(a, b) {
    document.write(a + " " + b);
}

function getArgString( args, start ) {
    var argStr = "";
    for( var i = start; i < args.length; i++ ) {
        if( argStr != "" ) {
            argStr = argStr + ", ";
        }
        argStr = argStr + "arguments[" + i + "]"
    }
    return argStr;
}

function setter(func) {
    var argStr = getArgString( arguments, 1 );
    eval( "func( " + argStr + ");" );
    var newSettter = function() {
        var argStr = getArgString( arguments, 0 );
        if( argStr == "" ) {
            argStr = "func";
        } else {
            argStr = "func, " + argStr;
        }
        return eval( "setter( " + argStr + ");" );
    }
    return newSettter;
}

setter(out, "hello")("world");
setter(out, "hello", "world")();

Je serais probablement déplacer le code dans getArgString dans le setter de la fonction elle-même si... un petit peu plus en sécurité depuis que j'ai utilisé 'eval est.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X