…or are there better ways to implement a Memoization?
Function.memoize = function(callableAsString)
{
var r = false, callable, code;
try
{
callable = eval(callableAsString);
if (typeof callable == "function" && typeof(Function.memoize.cache[callableAsString]) == "undefined")
{
code = callableAsString + " = function()" +
"{" +
"var cache = Function.memoize.cache['" + callableAsString + "'];" +
"var k = Json.stringify([this].concat(arguments));" +
"return cache.r[k] || (cache.r[k] = cache.c.apply(this, arguments));" +
"};" +
"true;";
if (r = eval(code))
{
Function.memoize.cache[callableAsString] = {c: callable, r: {}};
}
}
}
catch (e) {}
return r;
};
Function.memoize.cache = {};
Function.memoize("String.prototype.camelize");
Update based on the suggestions by Felix Kling
Function.memoize = function(callable)
{
var r = false;
if (typeof callable == "function")
{
var hash = callable.toString().hashCode();
r = function()
{
var cache = Function.memoize.cache[hash];
var key = Json.stringify([this].concat(arguments));
return cache.r[key] || (cache.r[key] = cache.c.apply(this, arguments));
}
if (!Function.memoize.cache)
{
Function.memoize.cache = {};
}
r.memoize = callable;
Function.memoize.cache[hash] = {c: callable, r: {}};
}
return r;
};
Function.unmemoize = function(callable)
{
if (callable.memoize && typeof callable.memoize == "function")
{
return callable.memoize;
}
else
{
return false;
}
};
String.prototype.camelize = Function.memoize(String.prototype.camelize);
String.prototype.camelize = Function.unmemoize(String.prototype.camelize);
I don’t see the need for eval… consider this implementation
Note that I deliberately ignored
thisin the key. The reason is thatthismay not be serializable bystringify(e.g. because of loops) and this is more the rule than the exception for example whenthis == windowi.e. in the global context.What is IMO useful is the ability to explictly pass the cache, so that you can for example create a separate cache for each instance or one shared cache for all instances by doing something like: