Recommandations associées : tutoriel javascript
apply(context,[arguments])
, call(context,param1,param2,...)
.Le currying est une technique qui transforme une fonction qui accepte plusieurs paramètres en une fonction qui accepte un seul paramètre (le premier paramètre de la fonction d'origine) et renvoie une nouvelle fonction qui accepte les paramètres restants et renvoie un résultat.
Par exemple, voici une fonction add()
, qui est une fonction utilisée pour traiter l'addition et la somme des paramètres (param1, params2,...) que nous lui passons.
// Voici la première fonction `add(x, y)` avec deux paramètres `x`, `y` function add(x, y){ renvoyer x + y ; } // Appelez la fonction `add()` et donnez deux paramètres `4` et `6` ajouter(4,6); // Simuler le fonctionnement de l'ordinateur, passer le premier paramètre 4 dans la première étape fonction ajouter(4, y){ retourner 4 + y ; } // Simuler le fonctionnement de l'ordinateur, passer le premier paramètre 6 à la deuxième étape fonction ajouter(4, 6){ retournez 4 + 6 ; }
À quoi cela ressemblerait-il si nous exécutions la fonction add()
? Voici une implémentation simple :
// La fonction curried add() peut accepter certains paramètres function add(x,y){ if (typeof y === 'indéfini') { fonction de retour (nouveau){ retourner x + nouveau ; } } // L'application complète renvoie x + y ; } // Test des appels console.log(typeof add(4)); // [Fonction] console.log(add(4)(6)); // 10 // Vous pouvez créer une fonction de sauvegarde let saveAdd = add(4); console.log(saveAdd(6)); // 10
Comme le montre la simple fonction curry add()
ci-dessus, la fonction peut accepter certaines fonctions, puis renvoyer une nouvelle fonction pour continuer à traiter les fonctions restantes.
Ici, nous créons une fonction de curry public, afin de ne pas avoir à implémenter le processus de curry complexe à l'intérieur de celle-ci à chaque fois que nous écrivons une fonction.
//Définir une fonction createCurry function createCurry(fn){ var tranche = Array.prototype.slice, stocké_args = slice.call(arguments,1); fonction de retour () { laissez new_args = slice.call(arguments), args = stocké_args.concat(new_args); return fn.apply(null,args); }}
Dans la fonction de currying publique ci-dessus :
arguments
n'est pas un vrai tableau, mais un objet avec un attribut length
, nous empruntons donc la méthode slice
à Array.prototype
pour nous aider à convertir arguments
en un vrai tableau, afin de faciliter notre meilleur fonctionnement.createCurry
pour la première fois, la variable stored_args
contient les paramètres sauf le premier paramètre, car le premier paramètre est la fonction dont nous avons besoin pour curry.createCurry
, la variable new_args
récupère les paramètres et les convertit en tableau.stored_args
via la fermeture et fusionne la valeur de la variable new_args
dans un nouveau tableau et l'assigne à la variable args
.fn.apply(null,args)
est appelée pour exécuter la fonction curry.Testons maintenant la fonction publique curry
// fonction ordinaire add() fonction ajouter(x, y){ renvoyer x + y ; } // Curry pour obtenir une nouvelle fonction var newAdd = createCurry(add,4); console.log(newAdd(6)); // 10 //Une autre manière simple console.log(createCurry(add,4)(6));// 10
Bien sûr, cela ne se limite pas au curry de deux paramètres, mais aussi de plusieurs paramètres :
// Paramètres multiples La fonction ordinaire function add (a,b,c,d){ renvoyer a + b + c + d ; } // Curry la fonction pour obtenir une nouvelle fonction, plusieurs paramètres peuvent être divisés à volonté console.log(createCurry(add,4,5)(5,6)); // Curry en deux étapes let add_one = createCurry(add,5); console.log(add_one(5,5,5));// 20 laissez add_two = createCurry(add_one,4,6); console.log(add_two(6)); // 21Grâce à
l'exemple ci-dessus, nous pouvons trouver une limitation, c'est-à-dire qu'il s'agit de deux paramètres ou de plusieurs paramètres, il ne peut être exécuté qu'en deux étapes, comme la formule suivante :
si on veut être plus flexible :
Comment le mettre en œuvre ?
Après les exercices ci-dessus, nous avons constaté que la fonction curry que nous avons créée présente certaines limites. Nous espérons que la fonction pourra être exécutée en plusieurs étapes :
// Créer une fonction curry qui peut être exécutée en plusieurs étapes. Fonction. , exécutez-le lorsque le nombre de paramètres est atteint : // Formule de fonction : fn(x,y,z,w) ==> fn(x)(y)(z)(w); laissez createCurry = (fn,...params)=> { laissez args = parsmes || let fnLen = fn.length; // Spécifie la longueur du paramètre de la fonction curry retour (...)res)=> { // Récupère tous les paramètres précédents via la chaîne de portée let allArgs = args.slice(0); // Copie en profondeur les paramètres args partagés par les fermetures pour éviter l'impact des opérations ultérieures (type référence) allArgs.push(...res); if(allArgs.length < fnLen){ // Lorsque le nombre de paramètres est inférieur à la longueur du paramètre de la fonction d'origine, appelez la fonction createCurry de manière récursive return createCurry.call(this,fn,...allArgs); }autre{ // Lorsque le nombre de paramètres est atteint, déclenche l'exécution de la fonction return fn.apply(this,allArgs); } } } // Fonction ordinaire function add(a,b,c,d){ avec plusieurs paramètres renvoyer a + b + c + d ; } //Testez la fonction de currying let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); //
Nous implémentons des fonctions de curry flexibles depuis plus de 10 ans, mais nous rencontrons ici un autre problème :
curryAdd(add,1,2,3,4)()
;add()
d'origine. C'est aussi une voie, mais comme nous satisfaisons ici le nombre de paramètres, nous sommes toujours confrontés à cette situation.Ici, il suffit de porter un jugement avant de renvoyer la fonction :
let createCurry = (fn,...params)=> { laissez args = parsmes || let fnLen = fn.length; // Spécifie la longueur du paramètre de la fonction curry si(longueur === _args.length){ //Ajouter un jugement. Si le nombre de paramètres pour la première fois est suffisant, appelez directement la fonction pour obtenir le résultat return fn.apply(this,args); } retour (...)res)=> { laissez allArgs = args.slice(0); allArgs.push(...res); if(allArgs.length < fnLen){ return createCurry.call(this,fn,...allArgs); }autre{ return fn.apply(this,allArgs); } }}
Ce qui précède peut être considéré comme une fonction curry flexible, mais elle n'est pas très flexible ici car nous ne pouvons pas contrôler le moment où elle est exécutée. Tant que le nombre de paramètres est suffisant, elle sera exécutée automatiquement. Que devons-nous faire si nous voulons obtenir un timing permettant de contrôler son exécution ?
Expliquons directement la formule de la fonction ici :
// Lorsque les paramètres sont satisfaits, appelez la fonction let createCurry = (fn,...params)=> { laissez args = parsmes || let fnLen = fn.length; // Spécifie la longueur du paramètre de la fonction curry //Bien sûr, le jugement ici doit être commenté, sinon le résultat sera exécuté directement lorsque le nombre de paramètres sera suffisant pour la première fois //if(length === _args.length){ // Ajoutez un jugement. Si le nombre de paramètres pour la première fois est suffisant, appelez directement la fonction pour obtenir le résultat //return fn.apply(this,args); //} retour (...)res)=> { laissez allArgs = args.slice(0); allArgs.push(...res); // Ici, il est jugé si les paramètres d'entrée sont supérieurs à 0. S'il est supérieur à 0, il est jugé si le nombre de paramètres est suffisant. // && ne peut pas être utilisé ici. Si && est utilisé, le résultat sera exécuté lorsque le nombre de paramètres sera suffisant. if(res.length > 0 || allArgs.length < fnLen){ return createCurry.call(this,fn,...allArgs); }autre{ return fn.apply(this,allArgs); } } } // Fonction ordinaire function add(a,b,c,d){ avec plusieurs paramètres renvoyer a + b + c + d ; } // Testez la fonction de curry contrôlable let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // fonction console.log(curryAdd(2)(3)(4)()); // 10 console.log(curryAdd(2)(3)()); // Renvoie NaN lorsque les paramètres ne suffisent pas.
Recommandations associées : Tutoriel d'apprentissage de JavaScript
Ce qui précède concerne les détails du curry de la fonction JavaScript. veuillez faire attention à php Autres articles connexes sur le site chinois !