Javascript Memoizer浅析


Posted in Javascript onOctober 16, 2014

以下来自John Hann的实现,这段代码引起了我的注意,它用巧妙的方法把方法调用的结果缓存起来了。

代码解析:

// memoize: 使用memoization来缓存的通用方法 

// func: 要被缓存的方法 

// context: 方法执行上下文 

// Note: 方法必须是外部可访问的,参数是可字符序列化的 

function memoize (func, context) { 

    function memoizeArg (argPos) { //参数表示原始方法中参数的位置 

        var cache = {}; //这个缓存的key是参数,value是执行结果 

        return function () { //返回一个函数闭包 

            if (argPos == 0) { //第一个参数,如果参数在缓存的key中不存在,就执行原始函数并且存储执行结果 

                if (!(arguments[argPos] in cache)) { 

                    cache[arguments[argPos]] = func.apply(context, arguments); 

                } 

                return cache[arguments[argPos]]; 

            } 

            else { //不是第一个参数,如果参数在缓存的key中不存在,就递归执行memoizeArg方法,原始方法中参数的位置-1 

                if (!(arguments[argPos] in cache)) { 

                    cache[arguments[argPos]] = memoizeArg(argPos - 1); 

                } 

                return cache[arguments[argPos]].apply(this, arguments); 

            } 

        } 

    } 

    var arity = func.arity || func.length; //func参数的长度,javascript中用length属性,其它的用arity属性 

    return memoizeArg(arity - 1); //从最后一个参数开始递归 

}

使用:

var mem = memoize(func, this);   

alert(mem.call(this,1,1,2));   

alert(mem.call(this,2,1,2));   

alert(mem.call(this,3,1,3));   

alert(mem.call(this,2,2,4));

看似简单,再一看好像也并不易懂,可是如果能对闭包的使用比较熟悉的话,就很好理解了。经过上面几次mem.call的调用之后,形成的是一棵树,每个节点都是一个闭包,每个闭包内有一个cache,每个cache的key都是树分支:

Javascript Memoizer浅析

(注:上面图中的“结果”也是一个闭包,只不过argPos为0而已)

不过方法有诸多,比如limboy说:

function Memoize(fn){ 

    var cache = {}; 

    return function(){ 

        var key = []; 

        for( var i=0, l = arguments.length; i < l; i++ ) 

            key.push(arguments[i]); 

        if( !(key in cache) ) 

            cache[key] = fn.apply(this, arguments); 

        return cache[key]; 

    }; 

}

实现更简易,不过把参数push到一个数组内,再把数组当key,而key是只支持字符串型的,因此这点在使用上需要注意(比如一个对象tostring之后可能只看到”[object Object]“了),它的功能比上面那个要弱一些。

改进这一点也不难,把参数另立一个对象即可,而原cache对象和这个另立的参数对象使用一个ID关联起来:

function Memoize(fn){ 

    var cache = {}, args = {}; 

    return function(){ 

        for( var i=0, key = args.length; i < key; i++ ) { 

            if( equal( args[i], arguments ) ) 

                return cache[i]; 

        } 

        args[key] = arguments; 

        cache[key] = fn.apply(this, arguments); 

        return cache[key]; 

    }; 

}

还有一些其他的办法,都可以写成简洁的函数式方法。

Javascript 相关文章推荐
自动生成文章摘要的代码[JavaScript 版本]
Mar 20 Javascript
jquery星级插件、支持页面中多次使用
Mar 25 Javascript
window.onload和$(function(){})的区别介绍
Oct 30 Javascript
js 剪切板应用clipboardData详细解析
Dec 17 Javascript
我的Node.js学习之路(一)
Jul 06 Javascript
jquery实现表单验证简单实例演示
Nov 23 Javascript
javascript的理解及经典案例分析
May 20 Javascript
Javascript实现汉字和拼音互转的终极方案
Oct 19 Javascript
JavaScript实现经典排序算法之选择排序
Dec 28 Javascript
vuejs实现标签选项卡动态更改css样式的方法
May 31 Javascript
AjaxFileUpload.js实现异步上传文件功能
Apr 19 Javascript
原生javascript制作贪吃蛇小游戏的方法分析
Feb 26 Javascript
让JavaScript和其它资源并发下载的方法
Oct 16 #Javascript
JavaScript实现继承的4种方法总结
Oct 16 #Javascript
JavaScript实现网页截图功能
Oct 16 #Javascript
JavaScript跨域方法汇总
Oct 16 #Javascript
js阻止事件追加的具体实现
Oct 15 #Javascript
用原生js做个简单的滑动效果的回到顶部
Oct 15 #Javascript
原生的html元素选择器类似jquery选择器
Oct 15 #Javascript
You might like
傻瓜化配置PHP环境――Appserv
2006/12/13 PHP
php上传文件中文文件名乱码的解决方法
2013/11/01 PHP
PHP获取php,mysql,apche的版本信息示例代码
2014/01/16 PHP
php实现的网络相册图片防盗链完美破解方法
2015/07/01 PHP
php curl获取https页面内容,不直接输出返回结果的设置方法
2019/01/15 PHP
javascript中的有名函数和无名函数
2007/10/17 Javascript
js 获取计算后的样式写法及注意事项
2013/02/25 Javascript
巧用jquery解决下拉菜单被Div遮挡的相关问题
2014/02/13 Javascript
Javascript中的 “&amp;” 和 “|” 详解
2017/02/02 Javascript
Vue中util的工具函数实例详解
2019/07/08 Javascript
vue使用i18n实现国际化的方法详解
2019/09/05 Javascript
vuex存储token示例
2019/11/11 Javascript
微信小程序实现点赞业务
2021/02/10 Javascript
[01:14:30]TNC vs VG 2019国际邀请赛淘汰赛 胜者组赛BO3 第二场 8.20.mp4
2019/08/22 DOTA
windows系统中python使用rar命令压缩多个文件夹示例
2014/05/06 Python
Python 爬虫爬取指定博客的所有文章
2016/02/17 Python
python中使用正则表达式的后向搜索肯定模式(推荐)
2017/11/11 Python
Python实现Dijkstra算法
2018/10/17 Python
python+OpenCV实现车牌号码识别
2019/11/08 Python
Python3 读取Word文件方式
2020/02/13 Python
python PIL模块的基本使用
2020/09/29 Python
美国女鞋品牌:naturalizer(娜然)
2016/08/01 全球购物
全球性的女装店:storets
2019/06/12 全球购物
给同学的道歉信
2014/01/16 职场文书
捐书寄语赠言
2014/01/18 职场文书
2014年健康教育实施方案
2014/02/17 职场文书
党员干部承诺书
2014/03/25 职场文书
小学生放飞梦想演讲稿
2014/08/26 职场文书
我的中国心演讲稿
2014/09/04 职场文书
学用政策心得体会
2014/09/10 职场文书
2014银行领导班子四风对照检查材料思想汇报
2014/09/25 职场文书
孕妇离婚协议书范本
2014/11/20 职场文书
2014五年级班主任工作总结
2014/12/05 职场文书
自荐信格式模板
2015/03/27 职场文书
给校长的建议书范文
2015/09/14 职场文书
HTML实现仿Windows桌面主题特效的实现
2022/06/28 HTML / CSS