Javascript 当被记忆的函数接受函数时,Lodash记忆键?

Javascript 当被记忆的函数接受函数时,Lodash记忆键?,javascript,optimization,lodash,memoization,Javascript,Optimization,Lodash,Memoization,我有一个大的数据收集,我经常通过首先应用过滤器来查询它。我想缓存和重用我使用的不同过滤器函数的结果,因为这部分可能很昂贵。这是一个粗略的模拟: 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

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

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”每次都作用于相同的数据

如何指定u0.memoize函数的键

上面的方法是有效的,但我使用的是函数的字符串表示,这感觉是错误的。有更好的办法吗

我担心当应用缩小时这是不安全的。在我的实际代码中,“memoize”部分位于一个ES6模块中,“a”和“b”部分位于另一个模块中,对“m”的调用位于几个不同的模块中,这些模块导入了“a”和“b”函数。字符串表示在这样的模块中是否稳定?转换为字符串表示是否很快

我能想到的唯一替代方法是创建一个string->function dictionary,这样您就可以执行类似于m(“a”)的调用,但如果名称错误,JavaScript Linter将无法识别

上面的方法是有效的,但我使用的是函数的字符串表示,这感觉是错误的

的确如此

我担心当应用缩小时这是不安全的

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

问题在于:

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有什么帮助吗?你的代码片段使用“符号”是如何解决这个问题的?真的很高兴得到这些建议,但我只是不明白。关于闭包问题,您是对的……不过,在这里只检测最外层的函数就足够了。
实现中的
WeakMap
。memoize
可以避免所有这些字符串化,因为您可以直接将函数对象用作键。
toMemoizeKey
函数应该用作调用中的第二个参数。它提供了一个简单的标记功能,将每个函数对象映射到一个唯一的整数。。。这样就避免了将函数转换为字符串的问题,但如果在多个模块中包含相同的函数,并且涉及到缩小,那么会识别出相同的函数吗?@fstr您所说的“在多个模块中包含”是什么意思?在不同地方多次出现的函数声明是不同的函数。因此,从我发布的问题来看,我的意思是,我在一个文件/模块中得到了函数f的一个定义,其他几个模块希望通过x调用它。回忆。如果我将WeakMap与_一起使用。memoize,即使使用了积极的缩小功能,这也会起作用吗?WeakMap将直接引用f而不是字符串表示?