Recommandations associées : "Tutoriel vidéo Javascript"
J'ai accidentellement vu la Fonction Curry lorsque je lisais des blogs techniques dans la communauté récemment , et j'ai également demandé à écrire à la main pour curry la fonction js J'ai pensé, quelle chose avancée est le curry ? Vous n'en avez jamais entendu parler ?
Je me suis penché sur le problème, je l'ai étudié et j'ai fait un peu de tri.
Qu'est-ce que le curry fonctionnel ? Voyons d'abord comment Wikipédia explique :
En informatique, Currying (anglais : Currying), également traduit par Currying ou Currying, consiste à transformer une fonction qui accepte plusieurs paramètres en une fonction qui en accepte un. une fonction avec un seul paramètre (le premier paramètre de la fonction d'origine) et renvoyant une nouvelle fonction qui accepte les paramètres restants et renvoie le résultat.Cette technique a été nommée par Christopher Strachey d'après le logicien Haskell Gary, bien qu'elle ait été inventée par Moses Schönfinkel et Gottlob Frege.
Intuitivement, le currying indique que "si vous corrigez certains paramètres, vous obtiendrez une fonction qui accepte les paramètres restants". Donc pour la fonction y^x à deux variables, si y=2 est fixe, on obtient la fonction 2^x à une variable.
Le concept de Currying n'est en fait pas compliqué. En termes faciles à comprendre : ne transmettez qu'une partie des paramètres à la fonction pour l'appeler, et laissez-la renvoyer une fonction pour traiter le reste. paramètres.
Si l'explication du texte est encore un peu abstraite, nous utiliserons la fonction add pour réaliser une implémentation simple de la fonction curry.
// 普通的add函数 function add(x, y) { return x + y } // add函数柯里化后 var curryingAdd = function(x) { return function(y) { return x + y; }; }; // 函数复用 var increment = curryingAdd(1); var addTen = curryingAdd(10); increment(2); // 3 addTen(2); // 12
En fait, les paramètres x et y de la fonction add sont transformés en une fonction qui reçoit d'abord x puis renvoie une fonction pour traiter le paramètre y. Maintenant, l'idée devrait être plus claire, c'est-à-dire appeler la fonction en ne transmettant qu'une partie des paramètres et la laisser renvoyer une fonction pour traiter les paramètres restants.
Après avoir lu ce qui précède sur le curry de la fonction add, la question se pose : à quoi sert de dépenser autant d'efforts pour encapsuler une couche ?
En fait, le premier exemple de curry de la fonction add a déjà impliqué la réutilisation de fonction provoquée par le curry de fonction. implémentez rapidement la fonction d'incrémentation et la fonction addTen via le curry de la fonction add. Regardons un exemple :
// 正常正则验证字符串 reg.test(txt) // 函数封装后 function check(reg, txt) { return reg.test(txt) } check(/\d+/g, 'test') //false check(/[a-z]+/g, 'test') //true // Currying后 function curryingCheck(reg) { return function(txt) { return reg.test(txt) } } var hasNumber = curryingCheck(/\d+/g) var hasLetter = curryingCheck(/[a-z]+/g) hasNumber('test1') // true hasNumber('testtest') // false hasLetter('21212') // false
L'exemple ci-dessus est une vérification régulière, appelez directement check. J'ai de nombreux endroits où je dois vérifier s'il y a des nombres, je dois en fait réutiliser le premier paramètre reg, afin que d'autres endroits puissent appeler directement hasNumber, hasLetter et d'autres fonctions afin que les paramètres puissent être réutilisés. appel.
var on = function(element, event, handler) { if (document.addEventListener) { if (element && event && handler) { element.addEventListener(event, handler, false); } } else { if (element && event && handler) { element.attachEvent('on' + event, handler); } } } var on = (function() { if (document.addEventListener) { return function(element, event, handler) { if (element && event && handler) { element.addEventListener(event, handler, false); } }; } else { return function(element, event, handler) { if (element && event && handler) { element.attachEvent('on' + event, handler); } }; } })();
Il peut être plus facile de comprendre s'il est écrit d'une autre manière. Ce qui précède consiste à déterminer d'abord le paramètre isSupport
.var on = function(isSupport, element, event, handler) { isSupport = isSupport || document.addEventListener; if (isSupport) { return element.addEventListener(event, handler, false); } else { return element.attachEvent('on' + event, handler); } }
Dans le processus de réalisation de projets, il est très courant d'encapsuler certaines opérations DOM. La première façon d'écrire ci-dessus est également relativement courante, mais jetons un coup d'œil à la deuxième façon d'écrire. la première façon d'écrire est de s'auto-exécuter puis de renvoyer un La nouvelle fonction détermine en fait quelle méthode sera utilisée à l'avance, pour éviter de porter des jugements à chaque fois .
Function.prototype.bind = function (context) { var _this = this var args = Array.prototype.slice.call(arguments, 1) return function() { return _this.apply(context, args) } }
Comme la liaison qui est souvent utilisée dans notre js, le mécanisme d'implémentation est le Currying.
Méthode d'encapsulation générale :
// 初步封装 var currying = function(fn) { // args 获取第一个方法内的全部参数 var args = Array.prototype.slice.call(arguments, 1) return function() { // 将后面方法里的全部参数和args进行合并 var newArgs = args.concat(Array.prototype.slice.call(arguments)) // 把合并后的参数通过apply作为fn的参数并执行 return fn.apply(this, newArgs) } }
Voici d'abord l'encapsulation préliminaire, en enregistrant les paramètres préliminaires par fermeture, puis en les épissant en obtenant les arguments restants, et enfin en exécutant la fonction de curry requise.
Cependant, la fonction ci-dessus présente encore quelques défauts si elle est renvoyée de cette manière, elle ne peut développer qu'un paramètre supplémentaire. Currying(a)(b)(c) ne semble pas être pris en charge (multi. -les appels de paramètres ne sont pas pris en charge), généralement dans ce cas, vous penserez à utiliser la récursivité et à l'encapsuler une couche plus loin.
// 支持多参数传递 function progressCurrying(fn, args) { var _this = this var len = fn.length; var args = args || []; return function() { var _args = Array.prototype.slice.call(arguments); Array.prototype.push.apply(args, _args); // 如果参数个数小于最初的fn.length,则递归调用,继续收集参数 if (_args.length < len) { return progressCurrying.call(_this, fn, _args); } // 参数收集完毕,则执行fn return fn.apply(this, _args); } }
Ceci est en fait basé sur l'ajout d'appels récursifs préliminaires. Tant que le nombre de paramètres est inférieur à la longueur fn.initiale, la récursion continuera à être exécutée.
Concernant les performances de Currying, il faut connaître les points suivants :
En fait, dans la plupart des applications, le principal goulot d'étranglement des performances est l'exploitation des nœuds DOM, la perte de performances de ce js est fondamentalement négligeable, le curry peut donc être utilisé directement et en toute sécurité.
// 实现一个add方法,使计算结果能够满足如下预期: add(1)(2)(3) = 6; add(1, 2, 3)(4) = 10; add(1)(2)(3)(4)(5) = 15; function add() { // 第一次执行时,定义一个数组专门用来存储所有的参数 var _args = Array.prototype.slice.call(arguments); // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值 var _adder = function() { _args.push(…arguments); return _adder; }; // 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回 _adder.toString = function () { return _args.reduce(function (a, b) { return a + b; }); } return _adder; } add(1)(2)(3) // 6 add(1, 2, 3)(4) // 10 add(1)(2)(3)(4)(5) // 15 add(2, 6)(1) // 9
En passant simplement quelques paramètres, vous pouvez créer dynamiquement de nouvelles fonctions utiles et cela apporte également un avantage supplémentaire, c'est-à-dire le ; la définition de la fonction mathématique est conservée, bien qu'il y ait plus d'un paramètre.
La fonction Currying est très simple d'utilisation, et l'utiliser au quotidien est pour moi tout simplement un plaisir. C’est un outil essentiel à avoir sous la main pour rendre la programmation fonctionnelle moins lourde et ennuyeuse.
Pour plus de connaissances sur la programmation, veuillez visiter : Introduction à la programmation ! !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!