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 相关文章推荐
jquery 模板的应用示例
Nov 12 Javascript
JQuery插件jcarousellite的参数中文说明
May 11 Javascript
JavaScript图片轮播代码分享
Jul 31 Javascript
详解JavaScript的另类写法
Apr 11 Javascript
jquery网页加载进度条的实现
Jun 01 jQuery
使用vue-cli导入Element UI组件的方法
May 16 Javascript
Vue.directive使用注意(小结)
Aug 31 Javascript
JavaScript动态生成表格的示例
Nov 02 Javascript
关于vue 项目中浏览器跨域的配置问题
Nov 10 Javascript
全面解析Vue中的$nextTick
Dec 24 Vue.js
vue集成一个支持图片缩放拖拽的富文本编辑器
Jan 29 Vue.js
js闭包和垃圾回收机制示例详解
Mar 01 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扩展
2013/06/13 PHP
PHP 开发者该知道的 5 个 Composer 小技巧
2016/02/03 PHP
php封装json通信接口详解及实例
2017/03/07 PHP
深入解析contentWindow, contentDocument
2013/07/04 Javascript
使用jquery的ajax需要注意的地方dataType的设置
2013/08/12 Javascript
引入autocomplete组件时JS报未结束字符串常量错误
2014/03/19 Javascript
JS实现表格数据各种搜索功能的方法
2015/03/03 Javascript
win7下安装配置node.js+express开发环境
2015/12/06 Javascript
必备的JS调试技巧汇总
2016/07/20 Javascript
AngularJS 面试题集锦
2016/09/06 Javascript
原生js实现倒计时--2018
2017/02/21 Javascript
bootstrap table表格客户端分页实例
2017/08/07 Javascript
浅析JavaScript中的特殊数据类型
2017/12/15 Javascript
原生js实现表格循环滚动
2020/11/24 Javascript
Python编程实现双链表,栈,队列及二叉树的方法示例
2017/11/01 Python
python实现基于SVM手写数字识别功能
2020/05/27 Python
python画出三角形外接圆和内切圆的方法
2018/01/25 Python
python 数字类型和字符串类型的相互转换实例
2018/07/17 Python
python同时遍历数组的索引和值的实例
2018/11/15 Python
python 多进程共享全局变量之Manager()详解
2019/08/15 Python
移动端Html5页面生成图片解决方案
2018/08/07 HTML / CSS
Alba Moda瑞士网上商店:独家意大利时尚女装销售
2016/11/28 全球购物
美国在线鲜花速递:ProFlowers
2017/01/05 全球购物
印度民族服装购物网站:BIBA
2019/08/05 全球购物
运动会入场词200字
2014/02/15 职场文书
博士毕业生自我鉴定范文
2014/04/13 职场文书
单位委托书怎么写
2014/08/02 职场文书
八年级上册语文教学计划
2015/01/22 职场文书
董事长助理岗位职责
2015/02/11 职场文书
幼儿园保育员随笔
2015/08/14 职场文书
2016年大学迎新工作总结
2015/10/14 职场文书
2015年秋学期师德师风建设工作总结
2015/10/23 职场文书
快消品行业营销模式与盈利模式分享
2019/09/27 职场文书
Lombok的详细使用及优缺点总结
2021/07/15 Java/Android
《雀魂PONG☆》4月1日播出 PV角色设定情报
2022/03/20 日漫
Win11使用CAD卡顿或者致命错误怎么办?Win11无法正常使用CAD的解决方法
2022/07/23 数码科技