...还是有更好的方法来实现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");
根据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);
答案 0 :(得分:0)
我认为不需要eval ...考虑这个实现
function memoize(f, cache)
{
if (!cache) cache = {};
return function()
{
var key = JSON.stringify(arguments);
return (cache[key] || (cache[key] = [f.apply(this, arguments)]))[0];
}
}
请注意,我故意忽略了密钥中的this
。原因是this
可能无法通过stringify
进行序列化(例如,由于循环),这更多的是规则而不是异常,例如当this == window
时,即在全局上下文中。
IMO有用的是显式传递缓存的能力,因此您可以通过执行以下操作为每个实例创建单独的缓存或为所有实例创建一个共享缓存:
function MyObj(...)
{
// every instance has its own cache
this.foo = memoize(function(...) { ... });
// there is one shared cache for all instances
this.bar = memoize(function(...) { ... }, MyObj.memoize_cache);
}
MyObj.memoize_cache = {};