zoukankan      html  css  js  c++  java
  • JavaScript 使用函数实现“历史记录”

    函数可以使用对象去记住先前操作的结果,从而避免多余的运算。

    比如我们现在测试一个费波纳茨算法,我们可以使用递归函数计算fibonacci数列,一个fibonacci数字是之前两个fibonacci数字之和,最前面的两个数字是0和1。代码如下:

    var count = 0;    //记录函数调用次数
     var fibonacci = function(n) {
        count++;
        return n < 2 ? n : fibonacci(n-1) + fibonacci(n-2);
     };
     for(var i = 0; i <= 10; i+=1) {
        console.log(i+":"+fibonacci(i));
     }
     console.log(count); // 453

    我们可以看到如上 fibonacci函数总共调用了453次,for循环了11次,它自身调用了442次,如果我们使用下面的记忆函数的话,那么就可以减少他们的运算次数,从而提高性能。

    思路:先使用一个临时数组保存存储结果,当函数被调用的时候,先查找是否已经有存储结果,如果有的话,就立即返回这个存储结果,没有的话,调用函数进行运算。代码如下:

     1 var count2 = 0;
     2 var fibonacci2 = (function(){
     3     var memo = [0,1];
     4     var fib = function(n) {
     5         var result = memo[n];
     6         count2++;
     7         if(typeof result !== 'number') {
     8             result = fib(n-1) + fib(n-2);
     9             memo[n] = result;
    10         }
    11         return result;
    12     };
    13     return fib;
    14  })();
    15  for(var j = 0; j <= 10; j+=1) {
    16     console.log(j+":"+fibonacci2(j));
    17  }
    18  console.log(count2); // 29

    这个函数也返回了同样的结果,但是只调用了函数29次,循环了11次,也就是说函数自身调用了18次,从而减少无谓的函数的调用及运算,下面我们可以把这个函数进行抽象化,以构造带记忆功能的函数,如下代码:

     1 var count3 = 0;
     2 var memoizer = function(memo,formula) {
     3     var recur = function(n) {
     4         var result = memo[n];
     5         count3++;   // 这句代码只是说明运行函数多少次,在代码中并无作用,实际使用上可以删掉
     6         if(typeof result !== 'number') {
     7             result = formula(recur,n);
     8             memo[n] = result;
     9         }
    10         return result;
    11     };
    12     return recur;
    13  };
    14  var fibonacci3 = memoizer([0,1],function(recur,n){
    15     return recur(n-1) + recur(n-2);
    16  });
    17  // 调用方式如下
    18  for(var k = 0; k <=10; k+=1) {
    19     console.log(k+":"+fibonacci3(k));
    20  }
    21  console.log(count3); // 29

    如上封装 memoizer 里面的参数是实现某个方法的计算公式,具体的可以根据需要自己手动更改,这里的思路无非就是想习惯使用对象去保存临时值,从而减少不必要的取值存储值的操作;

     

    学习资源:理解使用函数实现历史记录--提高性能

  • 相关阅读:
    典型用户模版和场景
    第一冲刺阶段——个人工作总结05
    第一冲刺阶段——个人工作总结04
    第一冲刺阶段——个人工作总结03
    第一冲刺阶段——个人工作总结02
    第一冲刺阶段——个人工作总结01
    学习进度条7
    构建之法阅读笔记06
    个人总结
    第十六周进度条
  • 原文地址:https://www.cnblogs.com/xiaochechang/p/5740837.html
Copyright © 2011-2022 走看看