Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

浅谈 JS 自记忆函数 #4

Open
KarthusLorin opened this issue Jun 25, 2020 · 0 comments
Open

浅谈 JS 自记忆函数 #4

KarthusLorin opened this issue Jun 25, 2020 · 0 comments

Comments

@KarthusLorin
Copy link
Owner

浅谈 JS 自记忆函数

最近阅读《JavaScript忍者秘籍》看到了一种有趣的函数:自记忆函数。

简介

何为自记忆函数?书中提到:

记忆化(memoization)是一种构建函数的处理过程,能够记住上次计算结果

通过这句话可以得出,自记忆函数其实就是能够记住上次计算结果的函数。在实现中,我们可以这样进行处理:当函数计算得到结果时,就将该结果按照参数存储起来。采取这种方式时,如果另外一个调用也使用相同的参数,我们则可以直接返回上次存储的结果而不是再计算一遍。

显而易见,像这样避免既重复又复杂的计算可以显著提高性能。对于动画中的计算、搜索不经常变化的数据或任何耗时的数学计算来说,记忆化这种方式是十分有用的。

一个自记忆函数的例子

下面这个例子展现自记忆函数的工作方式:

// 自记忆素数检测函数
function isPrime (value) {
  // 创建缓存
  if (!isPrime.answers) {
    isPrime.answers = {};
  }
  // 检查缓存的值
  if (isPrime.answers[value] !== undefined) {
    return isPrime.answers[value];
  }
  // 0和1不是素数
  var prime = value !== 0 && value !== 1;
  // 检查是否为素数
  for (var i = 2; i < value; i++) {
    if (value % i === 0) {
      prime = false;
      break;
    }
  }
  // 存储计算值
  return isPrime.answers[value] = prime
}

isPrime函数是一个自记忆素数检测函数,每当它被调用时:

首先,检查它的answers属性来确认是否已经有自记忆的缓存,如果没有,创建一个。

接下来,检查参数之前是否已经被缓存过,如果在缓存中找到该值,直接返回缓存的结果。

如果参数是一个全新的值,进行正常的素数检测。

最后,存储并返回计算值。

总结

自记忆函数有两个优点:

  • 由于函数调用时会寻找之前调用所得到的值,所以用户最终会乐于看到所获得的性能收益。
  • 它不需要执行任何特殊请求,也不需要做任何额外初始化,就能顺利进行工作。

但是,自记忆函数并不是完美的,它一样有着缺陷:

  • 任何类型的缓存都必然会为性能牺牲内存。
  • 很多人认为缓存逻辑不应该和业务逻辑混合,函数或方法只需要把一件事情做好。
  • 对自记忆函数很难做负载测试或估算算法复杂度,因为结果依赖于函数之前的输入。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant