Heim >Web-Frontend >js-Tutorial >Funktionsspeicher von JavaScript-Lernnotizen
Dieser Artikel stellt hauptsächlich den Funktionsspeicher von JavaScript vor. Der Herausgeber findet ihn recht gut. Jetzt werde ich den JavaScript-Quellcode mit Ihnen teilen und ihn als Referenz geben. Wenn Sie sich für JavaScript interessieren, folgen Sie bitte dem Editor, um einen Blick darauf zu werfen
Dieser Artikel erklärt die Implementierung des Funktionsspeichers und der Fibonacci-Sequenz und teilt sie mit allen. Die Details sind wie folgt
Definition
Der Funktionsspeicher bezieht sich auf das Zwischenspeichern des letzten Berechnungsergebnisses. Wenn beim nächsten Aufruf dieselben Parameter angetroffen werden, werden die Daten im Cache zurückgegeben direkt.
Zum Beispiel:
function add(a, b) { return a + b; } // 假设 memorize 可以实现函数记忆 var memoizedAdd = memorize(add); memoizedAdd(1, 2) // 3 memoizedAdd(1, 2) // 相同的参数,第二次调用时,从缓存中取出数据,而非重新计算一次
Prinzip
Eine solche Merkfunktion lässt sich im Prinzip nur von Ihnen umsetzen Sie müssen die Parameter mit den entsprechenden Ergebnisdaten kombinieren. Beim Aufruf wird beurteilt, ob die dem Parameter entsprechenden Daten vorhanden sind, und die entsprechenden Ergebnisdaten werden zurückgegeben.
Erste Version
Lass uns eine Version schreiben:
// 第一版 (来自《JavaScript权威指南》) function memoize(f) { var cache = {}; return function(){ var key = arguments.length + Array.prototype.join.call(arguments, ","); if (key in cache) { return cache[key] } else return cache[key] = f.apply(this, arguments) } }
Lass es uns testen:
var add = function(a, b, c) { return a + b + c } var memoizedAdd = memorize(add) console.time('use memorize') for(var i = 0; i < 100000; i++) { memoizedAdd(1, 2, 3) } console.timeEnd('use memorize') console.time('not use memorize') for(var i = 0; i < 100000; i++) { add(1, 2, 3) } console.timeEnd('not use memorize')
In Chrome dauert die Verwendung von „Memory“ etwa 60 ms. Wenn wir die Funktion „Memory“ nicht verwenden, dauert es etwa 1,3 ms.
Hinweis
Zweite Version
als Schlüsselwert. Schreiben wir eine Demo, um dieses Problem zu verifizieren:
var propValue = function(obj){ return obj.value } var memoizedAdd = memorize(propValue) console.log(memoizedAdd({value: 1})) // 1 console.log(memoizedAdd({value: 2})) // 1Beide geben 1 zurück, was offensichtlich ein Problem darstellt. Schauen wir uns also an, wie die Memoize-Funktion von Underscore implementiert ist:
// 第二版 (来自 underscore 的实现) var memorize = function(func, hasher) { var memoize = function(key) { var cache = memoize.cache; var address = '' + (hasher ? hasher.apply(this, arguments) : key); if (!cache[address]) { cache[address] = func.apply(this, arguments); } return cache[address]; }; memoize.cache = {}; return memoize; };Wie aus dieser Implementierung hervorgeht, verwendet der Unterstrich standardmäßig den ersten Parameter der Funktion als Schlüssel. Wenn Sie also
var add = function(a, b, c) { return a + b + c } var memoizedAdd = memorize(add) memoizedAdd(1, 2, 3) // 6 memoizedAdd(1, 2, 4) // 6direkt verwenden, liegt definitiv ein Problem vor, wenn Sie mehrere Parameter unterstützen möchten , müssen wir die Hasher-Funktion übergeben und den gespeicherten Schlüsselwert anpassen. Daher erwägen wir die Verwendung von JSON.stringify:
var memoizedAdd = memorize(add, function(){ var args = Array.prototype.slice.call(arguments) return JSON.stringify(args) }) console.log(memoizedAdd(1, 2, 3)) // 6 console.log(memoizedAdd(1, 2, 4)) // 7Wenn Sie JSON.stringify verwenden, kann auch das Problem gelöst werden, dass der Parameter ein Objekt ist, da gespeichert wird, was der String nach dem
-Objekt ist ist serialisiert .
Anwendbare Szenarien
var count = 0; var fibonacci = function(n){ count++; return n < 2? n : fibonacci(n-1) + fibonacci(n-2); }; for (var i = 0; i <= 10; i++){ fibonacci(i) } console.log(count) // 453Wir werden feststellen, dass die endgültige Zählung 453 beträgt , was bedeutet, dass die Fibonacci-Funktion 453 Mal aufgerufen wurde! Vielleicht denken Sie, ich habe gerade eine Schleife bis 10 gemacht, warum wurde es so oft aufgerufen, also analysieren wir es im Detail: Wenn fib(0) ausgeführt wird, wird es 1 Mal aufgerufen Bei der Ausführung von fib(1) wird es einmal aufgerufen Bei der Ausführung von fib(2) entspricht es dieses Mal fib(1) + fib(0) plus fib(2) selbst, insgesamt also 1 + 1 + 1 = 3 MalBei der Ausführung von fib(3) entspricht es dieses Mal fib(2) + fib(1) plus fib(3) selbst, insgesamt 3 + 1 + 1 = 5 MalBei der Ausführung von fib(4) entspricht es diesmal fib(3) + fib(2) plus fib(4) selbst, insgesamt 5 + 3 + 1 = 9 Mal Wenn fib(5) ausgeführt wird, entspricht es diesmal fib(4) + fib(3) plus fib(5) selbst, insgesamt 9 + 5 + 1 = 15 Mal
Bei der Ausführung von fib(6) entspricht dieses Mal fib(5) + fib(4) plus fib(6) selbst, insgesamt 15 + 9 + 1 = 25 Mal Bei der Ausführung von fib (7) Diesmal entspricht es fib(6) + fib(5) plus fib(7) selbst, insgesamt 25 + 15 + 1 = 41 Mal Bei der Ausführung von fib(8) Es entspricht fib(7) + fib(6). Diesmal wird fib(8) selbst hinzugefügt, insgesamt 41 + 25 + 1 = 67 Mal. Bei der Ausführung von fib(9) entspricht es fib(8) + fib(7) plus fib(9) Diesmal selbst, insgesamt 67 + 41 + 1 = 109 Mal Wenn fib(10) ausgeführt wird, entspricht es fib(9 ) + fib(8) plus fib(10) selbst dieses Mal, insgesamt 109 + 67 + 1 = 177 Mal
Die Gesamtzahl der Ausführungen beträgt also: 177 + 109 + 67 + 41 + 25 + 15 + 9 + 5 + 3 + 1 + 1 = 453 Mal!
Was wäre, wenn wir das Funktionsgedächtnis verwenden würden?
var count = 0; var fibonacci = function(n) { count++; return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2); }; fibonacci = memorize(fibonacci) for (var i = 0; i <= 10; i++) { fibonacci(i) } console.log(count) // 12Wir werden feststellen, dass die endgültige Gesamtanzahl 12 Mal beträgt. Aufgrund der Verwendung des Funktionsspeichers wird die Anzahl der Aufrufe von 453 Mal auf 12 Mal reduziert!
Vergessen Sie nicht, während Sie aufgeregt sind. Denken Sie: Warum ist es 12 Mal? Die Ergebnisse von 0 bis 10 werden jeweils einmal gespeichert. Soll es 11 Mal sein? Hey, woher kommt diese zusätzliche Zeit?
Daher müssen wir uns auch unsere Schreibmethode genau ansehen. In unserer Schreibmethode überschreiben wir tatsächlich die ursprüngliche Fibonacci-Funktion mit der generierten Fibonacci-Funktion. Wenn wir fibonacci(0) ausführen, wird die Funktion einmal ausgeführt ist { 0: 0}, aber wenn wir fibonacci(2) ausführen, führen wir fibonacci(1) + fibonacci(0) aus, da der Wert von fibonacci(0) 0 ist, das Ergebnis von !cache[address]
wahr ist und Fibonacci Die Funktion wird erneut ausgeführt. Es stellt sich heraus, dass die zusätzliche Zeit da ist!
Vielleicht haben Sie das Gefühl, dass Fibonacci in der täglichen Entwicklung nicht verwendet wird, und dieses Beispiel scheint wenig praktischen Wert zu haben. Tatsächlich wird dieses Beispiel verwendet, um ein Verwendungsszenario zu veranschaulichen, das heißt, wenn es eine große Anzahl von Wiederholungen gibt sind erforderlich. Für Berechnungen oder wenn eine große Anzahl von Berechnungen von vorherigen Ergebnissen abhängt, können Sie die Verwendung des Funktionsspeichers in Betracht ziehen. Und wenn Sie auf eine solche Szene stoßen, werden Sie es wissen.
Verwandte Empfehlungen:
Analyse der Bindungsnutzung von JavaScript-Funktionen
Detaillierte Erläuterung der Drosselung und Anti-Shake-Entprellung der JavaScript-Funktion
Erklären Sie die Verwendung der JavaScript-Funktionsbindung anhand von Beispielen
Das obige ist der detaillierte Inhalt vonFunktionsspeicher von JavaScript-Lernnotizen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!