【问题标题】:Lodash memoize key when the function being memoized accepts functions?当被记忆的函数接受函数时,Lodash memoize 键?
【发布时间】:2018-08-21 00:47:04
【问题描述】:

我有一个大型数据集合,我经常通过首先对其应用过滤器来查询它。我想缓存和重用我使用的不同过滤器函数的结果,因为这部分可能很昂贵。这是一个粗略的模拟:

const a = x => x + 1;
const b = x => x + 2;

const m = _.memoize( 
  f => (console.log('filtering data'), f(314159)),
  f => String(f)
 );

console.log(m(a));
console.log(m(b));
console.log(m(a));
console.log(m(b));

这里的“a”和“b”是我想要使用的过滤器函数,而“m”每次都作用于相同的数据。

如何为 _.memoize 函数指定密钥?

上述方法有效,但我使用的函数的字符串表示感觉不对。有没有更好的办法?

我担心应用缩小时这不安全。在我的实际代码中,“memoize”部分在一个 ES6 模块中,“a”和“b”部分在另一个模块中,对“m”的调用在导入“a”和“b”的几个不同模块中“ 功能。字符串表示会在这样的模块之间保持稳定吗?转换成字符串表示快吗?

我能想到的唯一替代方法是创建一个字符串 -> 函数字典,这样您就可以执行 m("a") 之类的调用,但如果名称错误,JavaScript linters 将不会接收。

【问题讨论】:

    标签: javascript optimization lodash memoization


    【解决方案1】:

    以上方法可行,但我使用的函数的字符串表示感觉不对。

    确实。

    我担心应用缩小时这不安全。

    不,缩小不是问题。不同的函数被缩小为不同的代码。

    问题是闭包:

    const addTo = x => y => x + y
    const a = addTo(1),
          b = addTo(2);
    console.log(String(a) === String(b));
    

    您只能通过对象身份可靠地比较函数。最好的方法可能是更新 Lodash 以使用不需要任何字符串化的 ES6 WeakMap。

    只要没有,就可以使用

    const id = Symbol("function identity");
    let count = 0;
    function toMemoizeKey(fn) {
        return fn[id] || (fn[id] = ++count);
    }
    

    【讨论】:

    • 谢谢!您能解释一下 WeakMap 将如何提供帮助以及您的 sn-p 使用“符号”如何解决这个问题吗?真的很高兴这些提示,但我只是没有遵循。您对关闭问题是正确的...不过,仅检测最外面的功能就足够了。
    • WeakMap 在_.memoize 的实现中将避免所有这些字符串化,因为您可以直接使用函数对象作为键。 toMemoizeKey 函数应该用作调用中的第二个参数。它提供了一个简单的标记功能,将每个函数对象映射到一个唯一的整数。
    • 谢谢,查了一下:developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… ... 这样可以避免函数被转换为字符串的问题,但是如果它被包含在多个模块中并且在缩小时会识别相同的函数参与?
    • @fstr “包含在多个模块中”是什么意思?一个函数声明多次出现在不同的地方就是不同的函数。
    • 所以从我发布的问题来看,我的意思是我在文件/模块中有一个函数 f 的定义,而其他几个模块想通过 _ 调用它。记住。如果我将 WeakMap 与 _ 一起使用。 memoize,即使使用激进的缩小,这也会起作用?而WeakMap会直接引用f而不是字符串表示?
    猜你喜欢
    • 2016-07-15
    • 2014-06-02
    • 1970-01-01
    • 2015-03-20
    • 2010-12-04
    • 1970-01-01
    • 2020-11-07
    • 2022-12-17
    • 2023-01-27
    相关资源
    最近更新 更多