内容要点:   可以将上次的计算结果缓存起来。在函数式编程当中,这中缓存技巧叫做 "记忆"。

需要注意的是,记忆只是一种编程技巧,本质上是牺牲算法的空间复杂度以换取更优的时间复杂度,在客户端JS中代码代码执行的时间复杂度往往成为瓶颈,因此在大多数场景下,这种牺牲空间换取时间的做法以提升程序执行效率的做法是非常可取的。

一.memorize()函数

下面的代码展示了一个高阶函数,memorize()接收一个函数作为实参,并返回带有记忆能力的函数。

//返回f()的带有记忆功能的版本

//只有当f()的实参的字符串表示都不相同它才会工作

function memorize(f){

var cache = {}; //将值保存在闭包内

return function(){

//将实参转换为字符串形式,并将其用做缓存的键

var key = arguments.length + Array.join.call(arguments,",");

if(key in cache) return cache[key];

else return cache[key] = f.apply(this,arguments);

};

}

代码分析:

memorize()函数创建一个新的对象,这个对象被当做缓存(的宿主)并赋值给一个局部变量,因此对于返回的函数来说它是私有的(在闭包中)。所返回的函数将它的实参数组转换成字符串,并将字符串用做缓存对象的属性名。如果在缓存中存在这个值,则直接返回它。

否则,就调用既定的函数对实参进行计算,将计算结果缓存起来并返回,下面的代码展示了如何使用memorize():

//返回两个整数的最大公约数

//使用欧几里德算法:

function gcd(a,b){   //这里省略对a和b的类型检查

var t;                  //临时变量用来存储交换数值

if(a<b) t=b,b=a,a=t;     //确保a>=b

while(b!=0) t=b,b=a%b,a=t; //这是求最大公约数的欧几里德算法

return a;

}

var gcdmemo = memorize(gcd);

gcdmemo(85,187) //=>17

//注意,当我们写一个递归函数时,往往需要实现记忆功能

//我们更希望调用实现了记忆功能的递归函数,而不是原递归函数

var factorial = memorize( function(n){ return (n<=1) ? 1 : n*factorial(n-1); });

factorial(5); //=>120.对于4-1的值也有缓存

《JS权威指南学习总结--8.8.4 记忆函数》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. oc底层方法调用流程

    1.对象方法保存到类对象里面,每个类对象中都有一个方法列表.类方法保存在元类中方法列表 a.通过isa指针去对应的类中查找: b.生成方法编号,根据方法编号查找对应的方法(找到只是最终实现地址,根据地 ...

  2. iOS 加载Image的两种方式

    Apple官方文档对于加载image提供了两个方法 + (nullable UIImage *)imageNamed:(NSString *)name; + (nullable UIImage *)i ...

  3. iOS strong与weak的使用

    strong修饰的属性是强指针类型的,weak修饰的属性是弱指针类型的 ARC对于内存中的对象管理机制,当某个对象没有被强指针指向的时候,该对象就会被销毁. 所以不适当的使用strong和weak修饰 ...

  4. Android studio使用smack连接xmpp服务器收发消息

    我使用的是ejabberd16.09的Linux版本,安装教程网上有很多,我在这里只介绍一下Android端连接.登录和收发消息的方法.文章最后附上了我写的一个demo,欢迎大家参考. ejabber ...

  5. Socket编程中 setsockopt的作用

    功能描述: 获取或者设置与某个套接字关联的选 项.选项可能存在于多层协议中,它们总会出现在最上面的套接字层.当操作套接字选项时,选项位于的层和选项的名称必须给出.为了操作套接字层的选项,应该 将层的值 ...

  6. 防止sql注入 查询的sql

    and userName like concat('%',#{userName},'%')

  7. Latex 使用小技巧

    Latex引用多篇参考文献 连续引用参考文献时中间中破折号连起来:[1,2,3,4]—>[1-4] 这是只需要在文档开始加入下面语句命令: \usepackage[numbers,sort&am ...

  8. springmvc框架下ajax请求传参数中文乱码解决

    springmvc框架下jsp界面通过ajax请求后台数据,传递中文参数到后台显示乱码 解决方法:js代码 运用encodeURI处理两次 /* *掩码处理 */ function maskWord( ...

  9. IntelliJ IDEA “Finds duplicated code”提示如何关闭

    发现重复的代码这个提示真的很烦啊,我们怎么关闭他呢. 设置在这里: Settings -> Editor -> Inspections -> General -> Duplic ...

  10. 基于html5 canvas 的强大图表插件【Chart.js】

    名词解释 Chart.js:是基于html5和canvas的强大图表插件,支持多样的图表形式,柱状线性饼环极地雷达等等: canvas:只兼容到IE9 excanvas.js:强大的第三方兼容插件,可 ...