Currying Origins et le nom du mathématicien Haskell Curry (le langage de programmation Haskell porte également son nom).
Le curry est également généralement appelé évaluation partielle. Sa signification est de transmettre des paramètres à une fonction étape par étape. Une fois chaque paramètre passé, appliquez partiellement les paramètres et renvoyez une fonction plus spécifique pour accepter les paramètres restants. Plusieurs couches de ces fonctions de paramètres partielles peuvent être imbriquées au milieu jusqu'à ce que le résultat final soit renvoyé.
Par conséquent, le processus de curry est un processus de passage progressivement des paramètres, de rétrécir progressivement la portée de l'application des fonctions et de les résoudre progressivement.
Curry d'une fonction de somme
Après une évaluation étape par étape, regardons un exemple simple
var concat3words = fonction (a, b, c) {return a + b + c; }; var concat3wordScurrying = function (a) {return function (b) {return function (c) {return a + b + c; }; }; }; console.log (Concat3Words ("foo", "bar", "baza")); // foo bar baza console.log (concat3wordScurrying ("foo")); // [fonction] console.log (concat3wordScurrying ("foo") ("bar") ("baza")); // Foo Bar BazaComme vous pouvez le voir, Concat3WordScurrying ("FOO") est une fonction, chaque appel renvoie une nouvelle fonction, qui accepte un autre appel, puis renvoie une nouvelle fonction jusqu'à ce que le résultat soit finalement renvoyé, et la distribution est résolue, et progresse la couche par couche. (PS: les caractéristiques des fermetures sont prises ici)
Alors maintenant, nous allons plus loin. Si nous avons besoin que plus de 3 paramètres soient passés, nous pouvons passer autant de paramètres que possible et sortir le résultat lorsque les paramètres ne sont pas passés?
Tout d'abord, ayons une implémentation normale:
var add = function (items) {return items.reduce (fonction (a, b) {return a + b}); }; console.log (add ([1,2,3,4]));Mais si vous demandez à multiplier chaque numéro par 10, puis ajoutez-le, alors:
var add = function (items, multi) {return items.map (function (item) {return item * multi;}). réduir (fonction (a, b) {return a + b}); }; console.log (Add ([1, 2, 3, 4], 10));Heureusement, il existe des fonctions de carte et de réduction. Si nous suivons ce modèle, nous devons ajouter 1 à chaque élément et le résumer, alors nous devons remplacer les fonctions dans MAP.
Jetons un œil à la mise en œuvre de la curryisation:
var adder = function () {var _args = []; return function () {if (arguments.length === 0) {return _args.reduce (fonction (a, b) {return a + b;}); } [] .push.apply (_args, [] .slice.call (arguments)); Return Arguments.Callee; }}; var sum = adder (); console.log (sum); // Sum de fonction (100 200) (300); // Le format d'appel est flexible, un ou plusieurs paramètres peuvent être entrés à la fois, et il prend en charge l'appel de chaîne à résumer (400); console.log (sum ()); // 1000 (calcul total)L'additionneur ci-dessus est une fonction en forme de curry, qui renvoie une nouvelle fonction, et la nouvelle fonction peut accepter de nouveaux paramètres par lots, en retardant jusqu'au dernier calcul.
Fonction générale de curry
Un curry plus typique résumera le dernier calcul en une fonction, puis passera cette fonction comme un paramètre dans la fonction de curry, ce qui est clair et flexible.
Par exemple, multiplier chaque terme par 10, nous pouvons passer la fonction de traitement comme un paramètre:
var currying = function (fn) {var _args = []; return function () {if (arguments.length === 0) {return fn.apply (this, _args); } Array.prototype.push.apply (_args, [] .slice.call (arguments)); Return Arguments.Callee; }}; var multi = function () {var total = 0; pour (var i = 0, c; c = arguments [i ++];) {total + = c; } return total; }; var sum = currying (multi); somme (100 200) (300); somme (400); console.log (sum ()); // 1000 (il n'est calculé que lorsque les appels vierges)De cette façon, sum = currying (multi), l'appel est très clair et l'effet d'utilisation est également brillant. Par exemple, pour accumuler plusieurs valeurs, vous pouvez utiliser plusieurs valeurs comme paramètres SUM (1,2,3), ou les appels de la chaîne de support, SUM (1) (2) (3)
Le fondement du curry
Le code ci-dessus est en fait une fonction d'ordre élevé. Une fonction d'ordre élevé fait référence à une fonction qui exploite une fonction. Il reçoit une ou plusieurs fonctions comme paramètres et renvoie une nouvelle fonction. De plus, les caractéristiques de la fermeture sont également invoquées pour enregistrer les paramètres entrés dans le processus intermédiaire. Tout de suite:
Les fonctions peuvent être passées comme paramètres
Les fonctions peuvent être utilisées comme valeur de retour de la fonction
Fermeture
Le rôle du curryculation
Calcul de retard. L'exemple ci-dessus est relativement faible.
Multiplexage des paramètres. Lorsque la même fonction est appelée plusieurs fois et que les paramètres passés sont principalement les mêmes, la fonction peut être un bon candidat pour le curry.
Créer des fonctions dynamiquement. Cela peut être généré dynamiquement après les résultats de calcul partiel, sur cette base, une nouvelle fonction est générée dynamiquement pour traiter l'activité suivante, omettant ainsi des calculs répétés. Ou vous pouvez créer dynamiquement une nouvelle fonction en appliquant une partie du sous-ensemble de paramètres à transmettre dans la fonction d'appel, ce qui enregistre les paramètres passés à plusieurs reprises (pas nécessairement à chaque fois dans le futur). Par exemple, une méthode auxiliaire pour les navigateurs d'événements pour ajouter des événements:
var addEvent = function (el, type, fn, capture) {if (window.addeventListener) {el.addeventListener (type, function (e) {fn.call (el, e);}, capture); } else if (window.attachevent) {el.attachevent ("on" + type, fonction (e) {fn.call (el, e);}); }};Chaque fois que vous ajoutez un événement, vous devez exécuter si ... sinon .... En fait, dans un navigateur, vous n'avez besoin de prendre une décision qu'une seule fois. Vous pouvez générer dynamiquement une nouvelle fonction basée sur le résultat après un jugement, et il n'est pas nécessaire de le recalculer à l'avenir.
var addEvent = (function () {if (window.addeventListener) {return function (el, stype, fn, capture) {el.addeventListener (stype, function (e) {fn.call (el, e);}, (capture));};} else if (window.atchevent) {return function (el, stype, fn, Capture) el.attachevent ("on" + stype, fonction (e) {fn.call (el, e);});};Cet exemple, une fois le premier jugement de si ... else ..., une partie du calcul est terminée, et une nouvelle fonction est créée dynamiquement pour traiter les paramètres transmis plus tard. Il s'agit d'une currylation typique.
La méthode function.prototype.bind est également une application Curry
Contrairement à la méthode d'appel / application qui s'exécute directement, la méthode BIND définit le premier paramètre au contexte de l'exécution de la fonction, et d'autres paramètres sont transmis à la méthode d'appel à leur tour (le corps de la fonction lui-même ne s'exécute pas, qui peut être considéré comme une exécution retardée), et crée dynamiquement et renvoie une nouvelle fonction, ce qui est confortable aux caractéristiques de courralisation.
var foo = {x: 888}; var bar = function () {console.log (this.x); } .bind (foo); // lier bar (); // 888Vous trouverez ci-dessous une simulation d'une fonction de liaison. TestBind crée et renvoie une nouvelle fonction. Dans la nouvelle fonction, la fonction qui veut vraiment exécuter l'entreprise est liée au contexte passé dans le paramètre réel, et l'exécution est retardée.
Function.prototype.testBind = fonction (scope) {var fn = this; //// Cela pointe vers une fonction qui appelle la méthode TestBind, return function () {return fn.apply (scope); }}; var testbindbar = bar.testBind (foo); // Bind Foo pour retarder l'exécution de console.log (testBindBar); // Fonction (voir, après bind, renvoie une nouvelle fonction qui détourne l'exécution) TestBindBar (); // 888Ici, nous devons prêter attention à la compréhension de cela dans le prototype.
L'analyse approfondie de l'article ci-dessus des fonctions currying dans le curry javascript est tout le contenu que je partage avec vous. J'espère que vous pourrez vous faire référence et j'espère que vous pourrez soutenir Wulin.com plus.