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

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

时间: 2024-08-30 14:13:27

JavaScript 使用函数实现“历史记录”的相关文章

JavaScript Function 函数深入总结

整理了JavaScript中函数Function的各种,感觉函数就是一大对象啊,各种知识点都能牵扯进来,不单单是 Function 这个本身原生的引用类型的各种用法,还包含执行环境,作用域,闭包,上下文,私有变量等知识点的深入理解. 函数中的return return 语句可以不带有任何返回值,在这种情况下( return; 或函数中不含 return 语句时),函数在停止执行后将返回 undefiend 值.这种用法一般在需要提前停止函数执行而又不需要返回值的情况下. return false

javascript中函数作用域之”提升“

javascript中函数作用域之变量提升 当我们在函数内部用关键字var声明一个变量的时候,此变量的作用域限制在当前函数. 提升:在一个作用域内部,不管一个变量用var声明的位置在哪里,这个变量属于当前整个作用域,并且在当前作用域的任何位置都可以访问它.在javascript中,这种行为/现象称之为"提升",即一个变量在一个作用域的任何位置用var声明,javascript引擎都会把这些用var声明的变量"移动"到当前作用域的开始处. 谈到javascript这种

JavaScript 常用函数总结

javascript函数:  ·常规函数  ·数组函数  ·日期函数  ·数学函数  ·字符串函数 .cookie函数 1.常规函数 javascript常规函数包括以下9个函数:  (1)alert函数:显示一个警告对话框,包括一个OK按钮.  (2)confirm函数:显示一个确认对话框,包括OK.Cancel按钮.  (3)escape函数:将字符转换成Unicode码.  (4)eval函数:计算表达式的结果.  (5)isNaN函数:测试是(true)否(false)不是一个数字. 

JavaScript调用函数的方法

摘要:这篇文章详细的介绍了Javascript中各种函数调用的方法及其原理,对于理解JavaScript的函数有很大的帮助! 一次又一次的,我发现,那些有bug的Javascript代码是由于没有真正理解Javascript函数是如何工作而导致的(顺便说一下,许多那样的代码是我写的).JavaScript拥有函数式编程的特性,当我们选择面对它的时候,这将成为我们前进的阻碍.  作为初学者,我们来测试五种函数调用的方法,从表面来看我们会认为那些函数与C#中函数的作用非常相似,但是我们一会儿可以看到

javascript篇-----函数作用域,函数作用域链和声明提前

在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于这类型的编程语言,javascript是没有块级作用域.取而代之的,javascript使用的是块级作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的. 在如下的所示的代码中,在不同位置定义了变量 i . j 和 k ,它们都在同一个作用域内——这三个变量在函数体内均是有定义

和demopu一起学习javascript ( concat函数 )

和demopu一起学习javascript (  concat函数 ) 定义和用法 concat方法可以把两个或者多个数组连接起来,组成一个新的数组. 语法 concat(array1,array2,......,arrayN) 参数 描述 array1 必需.该参数可以是具体的值,也可以是数组对象.可以是任意多个. 例子 1 var arr = ["George","John","Thomas"]; var arr2 = ["Jame

JavaScript encodeURI() 函数

encodeURI() 函数可把字符串作为 URI 进行编码. -------------------------------------------------------------------------------------------- 输入: <script type="text/javascript">document.write(encodeURI("http://www.w3school.com.cn")+ "<br

javascript常用函数整理

javascript函数: 1.禁止鼠标右键菜单代码块 function stop() {     return false; } document.oncontextmenu = stop; //禁用鼠标右键 document.ondragstart = stop; //禁止拖动 document.onselectstart = stop; //禁止选择 2.判断打开的页面是否存在父页面 if (window.top == window.self && window.parent == 

Javascript中函数的四种调用方式

一.Javascript中函数的几个基本知识点: 1.函数的名字只是一个指向函数的指针,所以即使在不同的执行环境,即不同对象调用这个函数,这个函数指向的仍然是同一个函数. 2.函数中有两个特殊的内部属性:arguments和this. arguments主要是用来保存函数参数,arguments中的callee属性主要是用来指向拥有当前arguments的函数(理解Javascript参数中的arguments对象). 3.在ECMAScript5中规范了另一个函数属性:caller(Opera