JavaScript 自记忆函数

60 篇文章 0 订阅
55 篇文章 1 订阅

如同前面所提到的,记忆化(memoization)是一种构建函数的处理过程,能够记住上次计算结果。在这个果壳里,当函数计算得到结果时就将该结果按照参数存储起来。采用这种方式时,如果另一个调用也使用相同的参数,我们则可以直接返回上次存储的结果而不是再计算一遍。像这样避免既重复又复杂的计算可以显著地提高性能。对于动画中的计算、搜索不经常变化的数据或任何耗时的数学计算来说,记忆化这种方式是十分有用的。

看看下面的例子,它使用了一个简单的(也的确是效率不高的)算法来计算素数。尽管这是一个复杂计算的简单例子,但它经常被应用到大计算量的场景中(例如可以引申到通过字符串生成MD5算法)。

从外表来说,这个函数和任何普通函数一样,但在内部我们会构建一个结果缓存,它会保存函数每次计算得到的结果。

质数(prime number)又称素数,有无限个。质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数。

console.log('------------计算先得到的值----------------');
function isPrime(value) {
  //创建缓存
  if (!isPrime.answers) {
    isPrime.answers = {}
  }
  //检查缓存的值
  if (isPrime.answers[value] !== undefined) {
    return isPrime.answers[value];
  }
  var prime = value !== 0 && value !== 1;//1 is not a prime
  for (var i = 2; i < value; i++) {
    if (value % i === 0) {
      prime = false;
      break;
    }
  }
  return isPrime.answers[value] = prime;//存储计算的值
}

//测试该函数是否正常工作
if (isPrime(5)) {
  console.log('5 is prime.');
}
if (isPrime.answers[5]) {
  console.log('The answer was cached!');
}

在isPrime函数中,首先通过检查它的answers属性来确认是否已经创建了一个缓存,如果没有创建,则新建一个:

//创建缓存
if (!isPrime.answers) {
    isPrime.answers = {}
}

只有第一次函数调用才会创建这个初始空对象,之后这个缓存就已经存在了。然后我们会检查参数中传值是否已经存储在缓存中:

//检查缓存的值
if (isPrime.answers[value] !== undefined) {
    return isPrime.answers[value];
}

 

这个缓存会针对参数中的值value来存储该值是否为素数(true或false)。如果我们在缓存中找到该值,函数会直接返回。

return isPrime.answers[value] = prime;//存储计算的值

这个缓存是函数自身的一个属性,所以只要该函数还存在,缓存也就存在。

最后的测试结果可以看到记忆函数生效了。

 

//测试该函数是否正常工作
if (isPrime(5)) {
  console.log('5 is prime.');
}
if (isPrime.answers[5]) {
  console.log('The answer was cached!');
}

 

这个方法具有两个优点:

1.由于函数调用时会寻找之前调用所得到的值,所以用户最终会乐于看到所获得的性能收益。

2.它几乎是无缝地发生在后台,最终用户和页面作者都不需要执行任何特殊请求,也不需要做任何额外的初始化,就能顺利进行工作。

当然这种方法并完美,还要权衡利弊

1.任何类型的缓存都必然会牺牲内存。

2.纯粹主义者会认为缓存逻辑不应该和业务逻辑混合,函数或方法只需要把一件事做好。

3.对于这类问题,很难做负载测试或估计算法复杂度,因为结果依赖于函数之前的输入。

参考《JavaScript忍者秘籍》

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值