我正在开发自己的函数式编程库,现在引用underscore
。
memoize _.memoize(function, [hashFunction])
通过缓存计算结果来记忆给定函数。对于加速慢速运行计算很有用。如果传递了一个可选的hashFunction,它将用于根据原始函数的参数计算用于存储结果的哈希键。默认的hashFunction只使用memoized函数的第一个参数作为键。
var fibonacci = _.memoize(function(n) {
return n < 2 ? n: fibonacci(n - 1) + fibonacci(n - 2);
});
以上代码能够自动记忆而不处理array
看起来有点神奇,我看到了下面的源代码,但内部设计仍然不清楚。
// Memoize an expensive function by storing its results.
_.memoize = function(func, hasher) {
var memoize = function(key) {
var cache = memoize.cache;
var address = hasher ? hasher.apply(this, arguments) : key;
if (!_.has(cache, address)) cache[address] = func.apply(this, arguments);
return cache[key];
};
memoize.cache = {};
return memoize;
};
有人能简单介绍一下发生了什么吗?
赞赏。
答案 0 :(得分:7)
memoize
有cache
(memoize.cache = {}
),用于存储函数调用的结果。当它被调用时,它确定address
以两种方式存储结果:调用hasher
函数或key
参数。
hasher函数的工作原理如下(来自下划线页面):
如果传递了一个可选的hashFunction,它将用于计算 用于存储结果的哈希键,基于参数 原始功能。默认的hashFunction只使用第一个 将记忆函数作为关键参数。
然后,它调用您传递的函数func.apply(...)
,并将结果存储在cache[address]
。
第二次调用memoized函数时,结果已经在缓存中(!_.has(..)
将返回false
)并且不会重复计算。
我不明白为什么它返回cache[key]
而不是cache[address]
很难...在我看来cache[address]
将是正确的选择。
正如评论中所指出的,您提供的代码不是memoize
的最新实现。这是最新的实现(1.6.0):
_.memoize = function(func, hasher) {
var memo = {};
hasher || (hasher = _.identity);
return function() {
var key = hasher.apply(this, arguments);
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
};
};
它的工作方式相同,只是它更优雅;如果没有提供hasher
函数,则它使用_.identity
作为键,这是一个只返回作为参数传递的值的函数:
_.identity = function(value) { return value; }
除此之外,cache
现在称为memo
,但工作方式相同。