使用 eval 记忆实现。 eval 的这种使用可以接受吗?

发布于 2024-12-05 10:46:57 字数 2126 浏览 0 评论 0原文

...或者有更好的方法来实现记忆化吗?

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遇见了你 2024-12-12 10:46:57

我不认为需要 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 = {};

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 = {};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文