Maison > Article > interface Web > Javascript est votre fonction d'ordre supérieur (application avancée)_compétences Javascript
Dans les langages de programmation habituels, les paramètres d'une fonction ne peuvent être que des types de base ou des références d'objet, et la valeur de retour ne peut être que des types de données de base ou des références d'objet. Mais en Javascript, les fonctions sont des citoyens de première classe et peuvent être transmises en tant que paramètres ou renvoyées en tant que valeurs de retour. La fonction dite d'ordre supérieur est une fonction qui peut prendre une fonction comme paramètre ou une fonction comme valeur de retour. Ces deux situations ont de nombreux scénarios d'application dans le développement réel. Cet article est un résumé de plusieurs scénarios d'application que j'ai rencontrés au cours de mon travail et de mes études.
Fonction de rappel
La réutilisation du code est l'un des critères importants pour mesurer une application. En extrayant la logique métier modifiée et en l'encapsulant dans la fonction de rappel, le taux de réutilisation du code peut être efficacement amélioré. Par exemple, la méthode forEach ajoutée aux tableaux dans ES5 parcourt le tableau et appelle la même fonction sur chaque élément.
array = {}; array.forEach = function(arr, fn){ for (var i = 0, len = arr.length; i < len; i++) { fn(arr[i], i, arr); } }
Concentrez l'activité sur la fonction de rappel sans avoir à réécrire le code de traversée à chaque fois.
Fonction partielle
En tant qu'application typique de sortie d'une fonction comme valeur de retour, il s'agit d'une fonction partielle. La fonction dite partielle fait référence à l'utilisation de la création d'une fonction qui appelle une autre partie, une fonction dont les paramètres ou les variables ont été prédéfinis. Quoi qu’il en soit, en regardant la définition, je ne comprends pas à quoi sert ce truc. Examinons d'abord des exemples. L'exemple le plus typique de fonctions partielles est le jugement de type.
Les objets Javascript ont trois attributs : les attributs de prototype, les attributs de classe et l'extensibilité. (Les étudiants qui ne savent pas devraient retourner lire le livre Rhino, page : 138) L'attribut class est une chaîne, qui n'est pas directement fournie en Javascript, mais nous pouvons utiliser Object.prototype.toString pour l'obtenir indirectement. Cette fonction renvoie toujours la forme suivante :
[Classe d'objet]
Nous pouvons donc écrire une série de fonctions isType.
Le code est le suivant :
isString = function(obj){ return Object.prototype.toString.call(obj) === "[object String]"; } isNumber = function(obj){ return Object.prototype.toString.call(obj) === "[object Number]"; } isArray = function(obj){ return Object.prototype.toString.call(obj) === "[object Array]"; }
La plupart des codes de ces fonctions sont répétés à l'heure actuelle, les fonctions d'ordre élevé font un début magnifique :
isType = function(type) { return function(obj) { return Object.prototype.toString.call(obj) === "[object " + type + "]"; } } isString = isType('String'); isNumber = isType('Number'); isArray = isType('Array');
Ainsi, la forme de renvoi d'une nouvelle fonction personnalisée en spécifiant certains paramètres est une fonction partielle.
Curry
Le currying est aussi appelé évaluation partielle. Une fonction de currying acceptera d'abord certains paramètres.Après avoir accepté ces paramètres, la fonction ne sera pas évaluée immédiatement, mais continuera à renvoyer une autre fonction. Les paramètres qui viennent d'être transmis sont enregistrés dans la fermeture formée par la fonction. Lorsque la fonction est réellement évaluée, tous les paramètres transmis seront utilisés pour l'évaluation en même temps.
var currying = function(fn) { var args = []; return function() { if (arguments.length === 0) { return fn.applay(this, args); } else { args = args.concat(arguments); return arguments.callee; } } }
Supposons que nous prenions comme exemple le calcul des dépenses quotidiennes d'un mois :
var currying = function(fn) { debugger; var args = []; return function() { if (arguments.length === 0) { return fn.apply(this, args); } else { Array.prototype.push.apply(args, arguments); return arguments.callee; } } } cost = function(){ var sum = 0; for (var i = 0, len = arguments.length; i < len; i++) { sum += arguments[i]; } return sum; } var cost = currying(cost); cost(100); cost(200); alert(cost())
Limitation des événements
Dans certains scénarios, certains événements peuvent être déclenchés à plusieurs reprises, mais la fonction de traitement des événements n'a pas besoin d'être exécutée à chaque fois. Par exemple, des calculs logiques complexes sont effectués dans l'événement window.resize. Si l'utilisateur modifie fréquemment la taille du navigateur, les calculs complexes auront un impact sérieux sur les performances. Parfois, ces calculs logiques n'ont pas besoin d'être déclenchés à chaque fois. seuls des calculs limités sont nécessaires. Pour le moment, nous devons ignorer certaines demandes d'événements en fonction de la période. Jetez un œil à la fonction de limitation suivante :
function throttle(fn, interval) { var doing = false; return function() { if (doing) { return; } doing = true; fn.apply(this, arguments); setTimeout(function() { doing = false; }, interval); } } window.onresize = throttle(function(){ console.log('execute'); }, 500);
En contrôlant le temps d'exécution des fonctions, vous pouvez atteindre un équilibre parfait entre le nombre d'exécutions de fonctions et les exigences fonctionnelles. Un autre événement est mousemove. Si nous lions cet événement à un élément DOM, l'événement sera déclenché à plusieurs reprises lorsque la souris passera sur l'élément.
L'événement est terminé
Pour certains événements qui peuvent être déclenchés fréquemment, nous souhaitons parfois effectuer une série d'opérations après la fin de l'événement. À ce stade, nous pouvons utiliser des fonctions d'ordre supérieur pour effectuer le traitement suivant :
function debounce(fn, interval) { var timer = null; function delay() { var target = this; var args = arguments; return setTimeout(function(){ fn.apply(target, args); }, interval); } return function() { if (timer) { clearTimeout(timer); } timer = delay.apply(this, arguments); } }; window.onresize = throttle(function(){ console.log('resize end'); }, 500);
Si l'événement est déclenché au cours de ce processus, effacez le dernier handle d'événement et reliez l'heure d'exécution.
Référence :
《Explication détaillée du nœud》
"Modèles de conception Javascript et pratiques de développement"