Ce qui suit est de la mise en œuvre de John Hann, et ce code a attiré mon attention, qui a mis en cache le résultat de l'appel de méthode avec des méthodes intelligentes.
Analyse de code:
La copie de code est la suivante:
// Mémoize: une méthode courante pour utiliser la mémorisation pour se cacher
// Func: méthode à mettre en cache
// Contexte: Contexte d'exécution de la méthode
// Remarque: la méthode doit être accessible en externe et les paramètres sont sérialisés
Fonction Memoize (Func, Context) {
Fonction MEMOIZEARG (Argpos) {// Le paramètre indique la position du paramètre dans la méthode d'origine
var cache = {}; // La clé de ce cache est le paramètre, et la valeur est le résultat d'exécution
return function () {// renvoie une fermeture de fonction
si (argpos == 0) {// le premier paramètre, si le paramètre n'existe pas dans la touche en cache, la fonction d'origine sera exécutée et le résultat d'exécution sera stocké
if (! (arguments [argpos] en cache)) {
cache [arguments [argpos]] = func.Apply (contexte, arguments);
}
Retour Cache [Arguments [Argpos]];
}
else {// pas le premier paramètre. Si le paramètre n'existe pas dans la touche mis en cache, la méthode MEMOIZEARG sera exécutée récursive. La position du paramètre dans la méthode d'origine -1
if (! (arguments [argpos] en cache)) {
cache [arguments [argpos]] = memoizearg (argpos - 1);
}
retourner cache [arguments [argpos]]. Appliquer (ceci, arguments);
}
}
}
var arity = func.arity || func.Length; // La longueur du paramètre FUNC est utilisée et l'attribut Arity est utilisé dans JavaScript.
Retour MemoizEarg (Arity - 1); // Recursion commence à partir du dernier paramètre
}
utiliser:
La copie de code est la suivante:
var mem = memoize (func, this);
alerte (mem.call (ceci, 1,1,2));
alerte (mem.call (ceci, 2,1,2));
alerte (mem.call (this, 3,1,3));
alerte (mem.call (ceci, 2,2,4));
Cela semble simple, mais cela ne semble pas facile à comprendre quand vous le regardez, mais si vous connaissez l'utilisation des fermetures, ce sera facile à comprendre. Après les appels ci-dessus à mem.call, un arbre est formé. Chaque nœud est une fermeture, chaque fermeture a un cache et chaque clé de cache est une branche d'arbre:
(Remarque: le "résultat" de l'image ci-dessus est également une fermeture, mais Argpos n'est que 0)
Mais il existe de nombreuses façons, comme Limboy a dit:
La copie de code est la suivante:
Fonction Memoize (fn) {
var cache = {};
return function () {
var key = [];
pour (var i = 0, l = arguments.length; i <l; i ++)
key.push (arguments [i]);
if (! (clé en cache))
cache [key] = fn.apply (this, arguments);
return cache [key];
};
}
L'implémentation est plus facile, mais poussez les paramètres dans un tableau, puis traitez le tableau comme une clé, et la clé ne prend en charge que le type de chaîne. Par conséquent, vous devez faire attention à ce point lorsque vous l'utilisez (par exemple, après un objet tostring, vous ne pouvez voir que "[objet objet]"), et sa fonction est plus faible que celle ci-dessus.
Il n'est pas difficile d'améliorer cela. Configurez simplement un autre objet avec le paramètre, et l'objet de cache d'origine et cet autre objet de paramètre sont associés à l'ID:
La copie de code est la suivante:
Fonction Memoize (fn) {
var cache = {}, args = {};
return function () {
pour (var i = 0, key = args.length; i <key; i ++) {
if (égal (args [i], arguments))
retour cache [i];
}
args [key] = arguments;
cache [key] = fn.apply (this, arguments);
return cache [key];
};
}
Il existe d'autres méthodes qui peuvent être écrites comme des méthodes fonctionnelles concises.