函数可以将先前操作的结果记录在某个对象里,从而避免无谓的重复运算。这种优化方式被称为记忆(memoization)。JavaScript的对象和数组要实现这种优化是非常方便的。

比如说,我们想要一个递归函数来计算Fibonacci数列。一个Fib数字是之前两个Fib数字的和。最前面的两个数字是0和1。

var count=0;
var fib=function(n){
count++;
return n<2?n:fib(n-1)+fib(n-2);
};
for(var i=0;i<=10;i++){
console.log(fib(i))
} //
//
//
//
//
//
//
//
//
//
// count
//

这样是可以工作的,但它做了很多无谓的工作,fib函数被调用了453次。如果我们让该函数具备记忆功能,就可以显著地减少运算量。

我们在一个名为memo的数组里保存我们的存储结果,存储结果可以隐藏在闭包中。当函数被调用时,这个函数首先检查结果是否已经存在,如果已经存在,就立刻返回这个结果。

var count=0;
var fibonacci=function(){
var memo=[0,1];
var fib=function(n){
count++;
var result=memo[n];
if(typeof result!=='number'){
result=fib(n-1)+fib(n-2);
memo[n]=result;
}
return result;
};
return fib;
}(); for(var i=0;i<=10;i++){
console.log(fibonacci(i))
}
//结果同上 count
//

这个函数返回同样的结果,但它只被调用了29次。

我们可以把这种技术推而广之,编写一个函数来帮助我们构造带记忆功能的函数。memoizer函数取得一个初始的memo数组和formula函数。它返回一个管理memo存储和在需要时调用formula函数的recur函数。我们把这个recur函数和它的参数传递给formula函数:

var memoizer=function(memo,formula){
var recur=function(n){
var result=memo[n];
if(typeof result!=='number'){
result=formula(recur,n);
memo[n]=result;
}
return result;
};
return recur;
};

现在我们可以使用memoizer函数来定义fibonacci函数,提供其初始的memo数组和formula函数:

var fibonacci=memoizer([0,1],function(recur,n){
return recur(n-1)+recur(n-2);
});

通过设计这种产生另一个函数的函数,极大的减少了我们的工作量。例如,要产生一个可记忆的阶乘函数,我们只需提供基本的阶乘公式即可:

var factorial=memoizer([1,1],function(recur,n){
return n*recur(n-1);
});

js-语言精粹-函数记忆的更多相关文章

  1. 《JS语言精粹》学习笔记 函数部分の闭包

    要理解闭包,首先要理解变量作用域,变量的作用域就两种,全局变量和局部变量,函数内部可以直接读取全局变量,函数外部无法读取函数内部的局部变量. 闭包定义:能读取函数内部局部变量的函数就是闭包,而只有函数 ...

  2. 学习笔记——JS语言精粹

    JS作用域是基于词法作用域的顶级对象. JS是一门弱类型语言,强类型能在编译时检测错误. JS是唯一一门所有浏览器都能识别的语言. 块注释对于被注释的代码是不安全的,例如/*  var rm=/a*/ ...

  3. js语言精粹读书笔记一

    一.语法 1.

  4. js语言精粹

    1.typeof null == “object” ,所以不能通过typeof ~ == "object",判断为对象   : a.判断为null的,直接~ === null:b. ...

  5. JavaScript语言精粹 笔记02 函数

    函数函数对象函数字面量调用参数返回异常给类型增加方法递归作用域闭包回调模块级联套用记忆   函数 1 函数对象 在JS中函数就是对象.对象是“名/值”对的集合并拥有一个连接到原型对象的隐藏连接.对象字 ...

  6. 《JavaScript语言精粹》之函数化

    写在前面 看到好多书评和读书笔记都说<JavaScript语言精粹>字字珠玑,名不虚传..当然,要看得懂才行 其实个人认为函数化部分不是很好,举的例子不是十分恰当,之前看不懂是因为被成功误 ...

  7. 模板语言变量,js变量,js自执行函数之前嵌套调用

    1.模板语言变量 前端html页面中展示 {{ nodeIp }} 2.js变量引用模板语言变量 把模板语言变量传递给js,js去执行页面操作(变量的转换,只适用于字符串) var IP = &quo ...

  8. JavaScript中对象与函数的某些事[JavaScript语言精粹-N1]

    今天在读<JavaScript语言精粹>的时候,关于函数的一个部分,始终觉得有点难以理解,代码如下: 1: var obj = (function(){ 2: var value = 0; ...

  9. js课程 3-10 js中字符串函数数组函数和其它语言中对应函数的区别和联系是什么

    js课程 3-10  js中字符串函数数组函数和其它语言中对应函数的区别和联系是什么 一.总结 一句话总结:js中是对象点方法的形式,这些方法都是对象的方法,而在php.java中却不是这样. 1.j ...

随机推荐

  1. 怎么把excel表格内的数据导入数据库?

    第一种方法: 思路:想要把excel表格内的数据直接导入数据库不是那么容易,可以把excel表格另存为.csv格式的文档(特点:内容以逗号分割):然后通过一系列的文档操作函数处理成为一个二维数组,然后 ...

  2. C#使用七牛云存储上传下载文件、自定义回调

    项目需要将音视频文件上传服务器,考虑并发要求高,通过七牛来实现. 做了一个简易的压力测试,同时上传多个文件,七牛自己应该有队列处理并发请求,我无论同时提交多少个文件,七牛是批量一个个排队处理了. 一个 ...

  3. postgresql-日志表

    pg_log,数据库日志表postgresqllog CREATE TABLE postgres_log ( log_time timestamp(3) with time zone, 日志生成时间 ...

  4. 【5】JMicro微服务-熔断降级

    如非授权,禁止用于商业用途,转载请注明出处作者:mynewworldyyl   1. 使用服务熔断降级特性,必须先启动Pubsub服务,服务监听服务,熔断器服务3个服务 先启动Pubsub及服务监听两 ...

  5. WebDriver高级应用实例(10)

    10.1控制HTML5语言实现的视频播放器 目的:能够获取html5语言实现的视频播放器视频文件的地址.时长.控制进行播放暂停 被测网页的网址: http://www.w3school.com.cn/ ...

  6. 转载:Java、C#双语版配套AES加解密示例

    转载,原文出处 http://www.cnblogs.com/lzrabbit/p/3639503.html 这年头找个正经能用的东西那是真难,网上一搜索一大堆,正经能用的没几个,得,最后还是得靠自己 ...

  7. freerdp服务器共享屏幕,skype lync终端显示黑屏的原因分析

    问题描述:freerdp支持远程桌面共享协议rdp,使用freerdp与skype终端进行远程桌面共享时.发送1080p 视频数据时 skype终端显示黑屏 经过分析,发现rdp协商参数大于一定值时, ...

  8. 全网最详细的Windows系统里Oracle 11g R2 Database服务器端(64bit)的下载与安装(图文详解)

    不多说,直接上干货! 环境: windows10系统(64位) 最好先安装jre或jdk(此软件用来打开oracle自带的可视化操作界面,不装也没关系:可以安装plsql,或者直接用命令行操作) Or ...

  9. php -- 表单多选

    ----- 011-form.html ----- <!DOCTYPE html> <html> <head> <meta http-equiv=" ...

  10. PHP多进程系列笔记(二)

    上一篇文章讲解了pcntl_fork和pcntl_wait两个函数的使用,本篇继续讲解PHP多进程相关新知识. 僵尸(zombie)进程 这里说下僵尸进程: 僵尸进程是指的父进程已经退出,而该进程de ...