javascript高级知识点——memoization
memoization是一种非常有用的优化技术,它缓存特定输入产生的相应结果。这样麻烦的查找和迭代计算可以尽可能的减少。
它基本的思想是针对特定的输入,已经计算过的结果都是通过缓存当中的数据直接返回而不是经过重复的计算。
实现记忆函数
我们可以简单的将memoization理解为记忆函数经过特定输入产生的结果。
下面是一种基本简单且实用的实现方法,可以很清晰的显示记忆函数的结构
function memoize( fn ) {
return function () {
// 将参数转为数组
var args = Array.prototype.slice.call(arguments);
// 创建缓存对象在目标函数对象里
fn.cache = fn.cache || {};
// 如果缓存当中有相应的结果直接从缓存中返回,否则重新计算并存储缓存对象
return args in fn.cache ? fn.cache[args] : fn.cache[args] = fn.apply(this, args);
};
}
为了方便我们可以更形象的理解记忆函数,我们将上面的三目运算符改成if语句,并添加log。
function memoize( fn ) {
return function () {
// 将参数转为数组
var args = Array.prototype.slice.call(arguments);
// 创建缓存对象在目标函数对象里
fn.cache = fn.cache || {};
// 如果缓存当中有相应的结果直接从缓存中返回,否则重新计算并存储缓存对象
var results;
if (args in fn.cache) {
console.log('返回结果来自于缓存:');
results = fn.cache[args];
}else {
console.log('返回结果来自于函数计算:');
results = fn.cache[args] = fn.apply(this, args);
}
return results
};
}
实际使用
这里我们将其运用到实际中去,下面是一个计算最大公约数的函数。但它不是学习的要点,我们只要知道它接收两个数字,并返回他们的最大公约数。
// 这是一个计算最大公约数的函数
function gcd(a ,b){
var t;
if (a < b) t = b, b = a, a = t;
while(b != 0) t=b, b= a%b, a=t;
return a;
} var cachedGcd = memoize(gcd); console.log(cachedGcd(85, 187)); // 返回结果来自于函数计算: 17 console.log(cachedGcd(85, 187)); // 返回结果来自于缓存:
在上面这段代码,可以看到经memoize处理过的gcd函数便具备记忆缓存的作用。不只是gcd,对于任何特定输入产生特定结果的函数都可以使用记忆函数。
简单测试
使用time简单的测试一下非记忆时,和记忆时函数调用的时间。在不同的浏览器有不同的结果,但是,整体来看记忆时的时间是比非记忆时要短的。
console.time('non-memoized')
cachedGcd(85,187);
console.timeEnd('non-memoized')
console.time('memoized')
cachedGcd(85,187);
console.timeEnd('memoized')
由于gcd函数涉及的运算相对比较少,这还不能很明显的体现记忆函数的优势,试想一下,如果一个函数运算量很大很大。那么通过缓存返回的结果将直接跳过这些复杂的运算,迅速返回结果。
javascript高级知识点——memoization的更多相关文章
- JavaScript高级知识点整理
一.JS中的数组 1.数组的三种定义方式 (1).实例化对象 var aArray=new Array(1,2,3,4,5); (2).快捷创建 var aTwoArray = [1,2,3,&quo ...
- javascript高级知识点——闭包
代码信息来自于http://ejohn.org/apps/learn/. 先给出一个权威的定义,函数对象可以通过作用域相互关联起来,函数体内的变量可以保存在函数的作用域内,这种特性称为闭包. 在闭包内 ...
- javascript高级知识点——函数的长度
代码信息来自于http://ejohn.org/apps/learn/. 函数的长度属性如何工作? function makeNinja(name){} function makeSamurai(na ...
- javascript高级知识点——指定上下文实现
代码信息来自于http://ejohn.org/apps/learn/. 当我们将一个对象的点击事件绑定到一个事件触发元素时会发生什么? <ul id="results"&g ...
- javascript高级知识点——内置对象原型
代码信息来自于http://ejohn.org/apps/learn/. 可以修改内置对象的方法. if (!Array.prototype.forEach) { Array.prototype.fo ...
- javascript高级知识点——继承
代码信息来自于http://ejohn.org/apps/learn/. 继承是如何工作的 function Person(){} function Ninja(){} Ninja.prototype ...
- javascript高级知识点——实例类型
代码信息来自于http://ejohn.org/apps/learn/. 分析一下对象的结构 function Ninja(){} var ninja = new Ninja(); console.l ...
- javascript高级知识点——函数原型
代码信息来自于http://ejohn.org/apps/learn/. 向函数的原型中添加方法 function Ninja(){} Ninja.prototype.swingSword = fun ...
- javascript高级知识点——临时作用域
代码信息来自于http://ejohn.org/apps/learn/. 自执行,临时,函数 (function(){ var count = 0; })(); 这是一个简单的自执行匿名函数. 做一个 ...
随机推荐
- Oracle安装基本步骤
安装数据库 .建立用户组及用户 groupadd oinstall groupadd dba groupadd oper useradd -g oinstall -G dba oracle passw ...
- C# 类属性封装、字段的详解
今日敲代码时,突然感觉对类的属性封装.字段有点犯迷糊了..连基础的都不知道了,那敲的代码怎么能严谨高效的.果断拿起各种高级编程.大全啥的翻起来~~这不再把自己的理解写下来(定义都是直接抄书的),献给同 ...
- mysql列名不能输入中文 解决办法
以前安装了mysql,今天下午做了个练习,每次列名为中文时总是报错.查资料显示说需要修改配置文件my.ini 我的路径是:C:\Program Files\MySQL\MySQL Server 5.5 ...
- JavaScript中的作用域链原理
执行环境 作用域链的形成与执行环境(Execution Environment)相关,在JavaScript当中,产生执行环境有如下3中情形: 1 进入全局环境 2 调用eval函数 3 调用func ...
- android ant 最简单的打包签名,混淆方法
使用ant打包,如果脚本都是我们自己一步一步来写的话,是一个比较麻烦的东西. 关于ant,我们详细看下: ant支持 ant debug,ant release等命令,我们需要签名混淆,那么就需要an ...
- js 函数声明与函数表达式
1,变量包括全局变量和局部变量,局部变量只能在函数内部访问.如果函数传参和全局变量一样的话,即使是给全局变量赋值,这里会把全局变量当成局部变量的. 如: 1: var x='x'; 2: 3: ...
- java中的File.separator
前些天遇到一个问题,困扰了好久,现在终于解决了. 问题:上传的图片不能正确显示. 我的开发环境是在Windows下,工程在Windows下能正常部署,上传的图片也可以正常的显 示.但是把工程部署在服务 ...
- [Head First Python]2. BIF(内置函数)
1- range() >>> for each in range(2): print(each) ... 0 1
- 第二章——第二节 IPC机制的概述和使用
一.Serialiable与Paracle ①.作用 ②.使用 二.Binder与AIDL ①.各自的作用 三.如何使用IPC机制 举例 四.IPC机制的原理 ①.流程图 ②.自己编译自动生成 ...
- EcStore中的App是什么东西?
Ecstore中的App不是手机上的App,它是一个Web应用包,集合了Web应用的后端PHP程序.Mysql数据表定义,以及前端HTML+CSS+JS展现,通常是实现某个业务功能,如购物车.促销.支 ...