Memoize implementation using eval. Is this use of eval acceptable?

徘徊边缘 提交于 2019-12-11 12:56:33

问题


...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);

回答1:


I don't see the need for eval... consider this implementation

function memoize(f, cache)
{
    if (!cache) cache = {};
    return function()
    {
        var key = JSON.stringify(arguments);
        return (cache[key] || (cache[key] = [f.apply(this, arguments)]))[0];
    }
}

Note that I deliberately ignored this in the key. The reason is that this may not be serializable by stringify (e.g. because of loops) and this is more the rule than the exception for example when this == window i.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:

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


来源:https://stackoverflow.com/questions/7497914/memoize-implementation-using-eval-is-this-use-of-eval-acceptable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!