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

     

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

  • 相关阅读:
    数据库基本操作
    守护线程
    线程使用的场景
    创建多线程
    用正则表达式去截取网页里文字的方法。参数为读取的网页源代码
    文章生成器,Split方法截取字符串。从硬盘读取文件,和向硬盘存储文件参考代码
    winform 阶段学习总结
    Windowform 窗体关联数据库存储,读取图片,参考代码
    windows form窗体应用程序,建一个记事本参考代码,重点是打开,保存,另存为
    js实现相册翻页,滚动,切换,轮播功能
  • 原文地址:https://www.cnblogs.com/xiaochechang/p/5740837.html
Copyright © 2011-2022 走看看