Easily cache results from Javascript functions
UPDATE: Adrian Quark has a much safer approach for the cache in his comment. I guess I should have tested mine better with other functions than the computational ones I was doing
A short Javascript function I made in a project to cache result from functions in Javascript. You can use this function where it makes sense to cache.
The cache method
cacheMethod.cache = {};
function cacheMethod(context, fn) {
var funcName = fn.toString();
funcName = funcName.substr('function '.length);
funcName = funcName.substr(0, funcName.indexOf('('));
context[funcName] = function() {
if (cacheMethod.cache[funcName] == null)
cacheMethod.cache[funcName] = {};
// Create a unique key of parameters
var key = Array.slice.call(arguments).join('|');
if (cacheMethod.cache[funcName][key] == null)
cacheMethod.cache[funcName][key] = fn.apply(this, arguments);
return cacheMethod.cache[funcName][key];
};
}
Usage
If we have a function like isPrime borrowed from John Resig:
function isPrime( num ) {
var prime = num != 1; // Everything but 1 can be prime
for ( var i = 2; i < num; i++ ) {
if ( num % i == 0 ) {
prime = false;
break;
}
}
return prime;
}
we can make the isPrime function cache-able with a single line of:
cacheMethod(this, isPrime);
No when we try to call the isPrime 100 times with a large prime number, this first round is calculated and all subsequent rounds use the cache. You can see the difference by removing the cacheMethod line.
for (var i=0; i<100; i++) document.write(isPrime(58750291)+'<br/>');
Full example here: cache.html.
Categories: Programming
A few problems with this:
1. the .name property is a much easier way to get the name of a function.
2. this won’t work with anonymous functions.
3. because it uses a global cache the cached values won’t be garbage collected even if the function goes away (e.g. it’s an event handler).
4. if your function takes a variable number of arguments and one contains a “|” the cache won’t work correctly.
5. if the function returns null this won’t be cached
6. the cache key won’t work with Object values since they don’t have a unique string representation. You need to use something like http://www.timdown.co.uk/jshashtable/ to get around that.
You can fix 1-5 with some minor modifications:
function memoise(f) { var cache = {}; return function () { var key = arguments.length+"|"+arguments.join("|"); if (cache[key] === undefined) { cache[key] = f.apply(this, arguments); } return cache[key]; } } isPrime = memoise(isPrime);Sorry about the formatting, the blog software seems to lose indentation even though I used a <code/> block.
[EDIT: Fixed
Gunnar Steinn]
I came up with an alternative version as well, looks like Adrian beat me to it.
My commentary is here:
http://www.reddit.com/r/programming/comments/9mm5o/easily_cache_results_from_javascript_functions/c0deuu8
I put Adrian’s thing in there, to get the formatting back. Woo!
Adrians approach works well except that arguments isn’t a proper Array in Javascript so you will have to use the “Array.slice.call(arguments).join(’|')” line from my code.
URL:
http://www.gunnarsteinn.com/2009/09/easily-cache-results-from-javascript-functions/wp-content/cache.html
Is don’t working
@jetm
Thanks, fixed the link