Skip to content
大纲

实现 JS 函数记忆

JavaScript 函数记忆是一种优化技术,用于缓存函数的输入和输出结果,以便在以后的调用中重用它们。这可以提高函数的性能,特别是当函数被频繁调用时。

什么是函数记忆?

函数记忆是一种缓存技术,它可以缓存函数的输入和输出结果。

当函数被调用时,它首先检查输入是否已经被缓存。如果已经缓存,则直接返回缓存的输出结果。否则,函数会计算输出结果并将输入和输出结果添加到缓存中,以便以后使用。

函数记忆可以显著提高函数的性能,特别是当函数被频繁调用时。然而,在实际应用中,它可能会增加代码的复杂性和内存占用,因此需要根据具体情况进行权衡。

js
function eq(a, b) {
  return Object.is(a, b)
}

function memoize(fn) {
  let lastArg
  let lastResult
  return function (arg) {
    if (lastArg !== undefined && eq(lastArg, arg)) {
      return lastResult
    }
    lastArg = arg
    lastResult = fn(arg)
    return lastResult
  }
}

斐波那契数列

这个函数的性能非常低下,因为它会在计算斐波那契数列的每一项时都重新计算前面的项。现在,我们将使用函数记忆来优化它。

js
function fibonacci(n) {
  if (n <= 1) {
    return n
  }
  return fibonacci(n - 1) + fibonacci(n - 2)
}

fibonacci(5)

现在,我们将使用函数记忆来优化它。

js
const cache = {}

function fibonacci(n) {
  if (n <= 1) return n
  if (cache[n]) return cache[n]

  const result = fibonacci(n - 1) + fibonacci(n - 2)
  cache[n] = result

  return result
}

console.log(fibonacci(5)) // 5
console.log(fibonacci(10)) // 55
console.log(fibonacci(15)) // 610
console.log(fibonacci(20)) // 6765
console.log(fibonacci(25)) // 75025
console.log(fibonacci(30)) // 832040

现在多次调用 fibonacci() 函数时,它会直接返回缓存中的结果,而不是每次都重新计算。这可以显著提高函数的性能。需要注意的是,函数记忆不是万能的解决方案。在某些情况下,它可能会增加代码的复杂性和内存占用。因此,我们需要根据具体情况进行权衡。在实际应用中,我们可以使用现有的 JavaScript 库来自动实现函数记忆,例如 memoizee 和 lru-memoize 等