Das Folgende stammt aus der Implementierung von John Hann. Dieser Code hat meine Aufmerksamkeit erregt. Er verwendet eine clevere Methode, um die Ergebnisse von Methodenaufrufen zwischenzuspeichern.
Code-Analyse:
// memoize: Eine allgemeine Methode zum Caching mithilfe der Memoisierung
// func: Methode, die zwischengespeichert werden soll
// Kontext: Methodenausführungskontext
// Hinweis: Auf die Methode muss von außen zugegriffen werden können und die Parameter müssen durch Zeichen serialisierbar sein
Funktion memoize (func, context) {
Funktion memoizeArg (argPos) { //Parameter gibt die Position des Parameters in der ursprünglichen Methode
an
var Cache = {}; // Der Schlüssel dieses Caches ist der Parameter und der Wert ist das Ausführungsergebnis
return function () { // Einen Funktionsabschluss zurückgeben
If (argPos == 0) { //Der erste Parameter. Wenn der Parameter nicht im zwischengespeicherten Schlüssel vorhanden ist, führen Sie die ursprüngliche Funktion aus und speichern Sie das Ausführungsergebnis
If (!(arguments[argPos] in Cache)) {
Cache[Argumente[ArgPos]] = func.apply(Kontext, Argumente);
return cache[arguments[argPos]];
Sonst {// ist nicht der erste Parameter. Wenn der Parameter nicht im Cache-Schlüssel vorhanden ist, wird die Memoizearg-Methode rekursiv ausgeführt. Die Position des Parameters in der ursprünglichen Methode-1
If (!(arguments[argPos] in Cache)) {
cache[arguments[argPos]] = memoizeArg(argPos - 1);
return cache[arguments[argPos]].apply(this, arguments);
}
}
var arity = func.arity ||. func.length; //Die Länge des func-Parameters, das Längenattribut wird in JavaScript verwendet und das Arity-Attribut wird für andere verwendet
Return memoizeArg(arity - 1); //Rekursion vom letzten Parameter
}
Verwendung:
Code kopieren
Der Code lautet wie folgt:
var mem = memoize(func, this);
Alert(mem.call(this,1,1,2));
Alert(mem.call(this,2,1,2));
Alert(mem.call(this,3,1,3));
alarm(mem.call(this,2,2,4));
Es scheint einfach, ist aber auf den ersten Blick möglicherweise nicht leicht zu verstehen. Wenn Sie jedoch mit der Verwendung von Verschlüssen vertraut sind, wird es leicht zu verstehen sein. Nach den oben genannten mehreren Aufrufen von mem.call wird ein Baum gebildet, jeder Knoten ist ein Abschluss, jeder Abschluss hat einen Cache und der Schlüssel jedes Caches ist ein Baumzweig:
(Hinweis: Das „Ergebnis“ im obigen Bild ist ebenfalls ein Abschluss, aber argPos ist 0)
Aber es gibt viele Möglichkeiten, zum Beispiel sagte Limbboy:
Code kopieren
Der Code lautet wie folgt:
Funktion Memoize(fn){
var Cache = {};
Rückgabefunktion(){
var key = [];
for( var i=0, l = arguments.length; i < l; i )
key.push(arguments[i]);
If( !(key in Cache) )
Cache[key] = fn.apply(this, arguments);
Cache[Schlüssel] zurückgeben;
};
}
Die Implementierung ist einfacher, aber verschieben Sie die Parameter in ein Array und verwenden Sie das Array dann als Schlüssel. Der Schlüssel unterstützt nur den Zeichenfolgentyp. Daher müssen Sie bei der Verwendung (z. B. eines Objekts) darauf achten darf nur nach tostring „[object Object]“ gesehen werden, seine Funktion ist schwächer als die obige.
Es ist nicht schwer, dies zu verbessern. Erstellen Sie einfach ein separates Objekt für den Parameter, und das ursprüngliche Cache-Objekt und dieses separate Parameterobjekt werden mit einer ID verknüpft:
Code kopieren
for( var i=0, key = args.length; i < key; i ) {
If( equal( args[i], arguments ) )
Cache zurückgeben[i];
}
args[key] = Argumente;
Cache[key] = fn.apply(this, arguments);
Cache[Schlüssel] zurückgeben;
};
}
Es gibt andere Methoden, die als prägnante funktionale Methoden geschrieben werden können.