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 相关文章推荐
用js实现的页面关键字密度查询代码
Dec 27 Javascript
javascript去除字符串中所有标点符号和提取纯文本的正则
Jun 07 Javascript
jQuery中hasClass()方法用法实例
Jan 06 Javascript
jQuery动画与特效详解
Feb 01 Javascript
js如何准确获取当前页面url网址信息
Sep 13 Javascript
使用bootstrap3开发响应式网站
May 12 Javascript
基于jQuery选择器之表单对象属性筛选选择器的实例
Sep 19 jQuery
element-ui 表格实现单元格可编辑的示例
Feb 26 Javascript
Angular使用cli生成自定义文件、组件的方法
Sep 04 Javascript
解决微信小程序云开发中获取数据库的内容为空的方法
May 15 Javascript
js之切换全屏和退出全屏实现代码实例
Sep 09 Javascript
jquery实现商品sku多属性选择功能(商品详情页)
Dec 20 jQuery
让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
第八节 访问方式 [8]
2006/10/09 PHP
PHP实现的超长文本分页显示功能示例
2018/06/04 PHP
PHP PDO和消息队列的个人理解与应用实例分析
2019/11/25 PHP
Javascript 面向对象 继承
2010/05/13 Javascript
url地址自动加#号问题说明
2010/08/21 Javascript
深入理解JavaScript系列(6) 强大的原型和原型链
2012/01/15 Javascript
js实现点击后将文字或图片复制到剪贴板的方法
2014/08/04 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
JS中用try catch对代码运行的性能影响分析
2016/12/26 Javascript
js设置文字颜色的方法示例
2016/12/30 Javascript
js模拟微博发布消息
2017/02/23 Javascript
详解bootstrap用dropdown-menu实现上下文菜单
2017/09/22 Javascript
vue同步父子组件和异步父子组件的生命周期顺序问题
2018/10/07 Javascript
Vue 同步异步存值取值实现案例
2020/08/05 Javascript
[35:34]Liquid vs Winstrike 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
解决python写的windows服务不能启动的问题
2014/04/15 Python
编写Python脚本来获取Google搜索结果的示例
2015/05/04 Python
Python合并两个字典的常用方法与效率比较
2015/06/17 Python
python实现发送邮件及附件功能
2021/03/02 Python
Python 中Pickle库的使用详解
2018/02/24 Python
python 文件查找及内容匹配方法
2018/10/25 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
2019/04/11 Python
python命令 -u参数用法解析
2019/10/24 Python
python之pymysql模块简单应用示例代码
2019/12/16 Python
Python 如何实现访问者模式
2020/07/28 Python
python程序实现BTC(比特币)挖矿的完整代码
2021/01/20 Python
全球最大的在线旅游公司:Expedia
2017/11/16 全球购物
数以千计的折扣工业产品:ESE Direct
2018/05/20 全球购物
物业客服专员岗位职责
2013/11/30 职场文书
路政管理毕业自荐书范文
2014/02/10 职场文书
遗嘱公证书标准样本
2014/04/08 职场文书
2014年村计划生育工作总结
2014/11/14 职场文书
营业用房租赁协议书
2014/11/26 职场文书
2015年教育实习工作总结
2015/04/24 职场文书
2015年公务员试用期工作总结
2015/05/28 职场文书
婚礼领导致辞大全
2015/07/28 职场文书