使用eval记住实现。这种使用eval是否可以接受?

时间:2011-09-21 09:57:54

标签: javascript eval memoization

...还是有更好的方法来实现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);

1 个答案:

答案 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 = {};