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 相关文章推荐
encode脚本和normal脚本混用的问题与解决方法
Mar 08 Javascript
关于jquery.validate1.9.0前台验证的使用介绍
Apr 26 Javascript
JS Jquery 遍历,筛选页面元素 自动完成(实现代码)
Jul 08 Javascript
jquery 漂亮的删除确认和提交无刷新删除示例
Nov 13 Javascript
使用jquery prev()方法找到同级的前一个元素
Jul 11 Javascript
javascript性能优化之DOM交互操作实例分析
Dec 12 Javascript
微信小程序 wxapp导航 navigator详解
Oct 31 Javascript
Angular将填入表单的数据渲染到表格的方法
Sep 22 Javascript
js捆绑TypeScript声明文件的方法教程
Apr 13 Javascript
vue使用混入定义全局变量、函数、筛选器的实例代码
Jul 29 Javascript
node.js中对Event Loop事件循环的理解与应用实例分析
Feb 14 Javascript
HTML元素拖拽功能实现的完整实例
Dec 04 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 运行效率总结(提示程序速度)
2009/11/26 PHP
php中一个完整表单处理实现代码
2011/11/10 PHP
php+mysqli批量查询多张表数据的方法
2015/01/29 PHP
Yii2.0 模态弹出框+ajax提交表单
2016/05/22 PHP
PhpStorm的使用教程(本地运行PHP+远程开发+快捷键)
2020/03/26 PHP
JavaScript高级程序设计(第3版)学习笔记12 js正则表达式
2012/10/11 Javascript
javascript中Object使用详解
2015/01/26 Javascript
JS实现仿新浪微博发布内容为空时提示功能代码
2015/08/19 Javascript
JavaScript中this详解
2015/09/01 Javascript
简单谈谈Javascript中类型的判断
2015/10/19 Javascript
JS闭包与延迟求值用法示例
2016/12/22 Javascript
基于Vue实现页面切换左右滑动效果
2020/06/29 Javascript
Angular2+如何去除url中的#号详解
2017/12/20 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
2018/03/21 Javascript
vue进入页面时滚动条始终在底部代码实例
2019/03/26 Javascript
vue-cli3 项目优化之通过 node 自动生成组件模板 generate View、Component
2019/04/30 Javascript
JavaScript实现页面中录音功能的方法
2019/06/04 Javascript
微信小程序swiper左右扩展各显示一半代码实例
2019/12/05 Javascript
javascript+css实现进度条效果
2020/03/25 Javascript
通过实例解析javascript Date对象属性及方法
2020/11/04 Javascript
python搭建简易服务器分析与实现
2012/12/15 Python
python僵尸进程产生的原因
2017/07/21 Python
Python处理CSV与List的转换方法
2018/04/19 Python
python 中文件输入输出及os模块对文件系统的操作方法
2018/08/27 Python
python 循环读取txt文档 并转换成csv的方法
2018/10/26 Python
Win 10下Anaconda虚拟环境的教程
2020/05/18 Python
python如何查看安装了的模块
2020/06/23 Python
python hmac模块验证客户端的合法性
2020/11/07 Python
乐天旅游台湾网站:Rakuten Travel TW
2017/06/01 全球购物
幼儿园长自我鉴定
2013/10/17 职场文书
甜品蛋糕店创业计划书范文
2014/02/06 职场文书
上海世博会志愿者口号
2014/06/17 职场文书
二手房购房协议书范本
2014/10/05 职场文书
社区三八妇女节活动总结
2015/02/06 职场文书
高考作弊检讨书1500字
2015/02/16 职场文书
GPU服务器的多用户配置方法
2022/07/07 Servers