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 相关文章推荐
dropdownlist之间的互相联动实现(显示与隐藏)
Nov 24 Javascript
读jQuery之四(优雅的迭代)
Jun 20 Javascript
Raphael一个用于在网页中绘制矢量图形的Javascript库
Jan 08 Javascript
jquery ui dialog替代confirm实例分析
Jan 25 Javascript
避免jQuery名字冲突 noConflict()方法
Jul 30 Javascript
bootstrap fileinput 插件使用项目总结(经验)
Feb 22 Javascript
JavaScript引用类型Date常见用法实例分析
Aug 08 Javascript
浅析vue-router原理
Oct 19 Javascript
JavaScript实现新年倒计时效果
Nov 17 Javascript
JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】
Feb 24 Javascript
javascript中contains是否包含功能实现代码(扩展字符、数组、dom)
Apr 07 Javascript
JavaScript如何优化逻辑判断代码详解
Jun 08 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简单静态页生成过程
2008/03/27 PHP
淘宝ip地址查询类分享(利用淘宝ip库)
2014/01/07 PHP
PHP使用CURL模拟登录的方法
2015/07/08 PHP
php实现处理输入转义字符的代码
2015/11/08 PHP
PHP分享图片的生成方法
2018/04/25 PHP
HTML页面如何象ASP一样接受参数
2007/02/07 Javascript
juqery 学习之三 选择器 可见性 元素属性
2010/11/25 Javascript
js对象的构造和继承实现代码
2010/12/05 Javascript
Js获取数组最大和最小值示例代码
2013/10/29 Javascript
js 实现的可折叠留言板(附源码下载)
2014/07/01 Javascript
JavaScript获取图片真实大小代码实例
2014/09/24 Javascript
Bootstrap进度条组件知识详解
2016/05/01 Javascript
Bootstrap组件(一)之菜单
2016/05/11 Javascript
用JavaScript动态建立或增加CSS样式表的实现方法
2016/05/20 Javascript
jQuery实现div横向拖拽排序的简单实例
2016/07/13 Javascript
详解前后端分离之VueJS前端
2017/05/24 Javascript
AngularJS 实现点击按钮获取验证码功能实例代码
2017/07/13 Javascript
vue+高德地图写地图选址组件的方法
2019/05/18 Javascript
微信小程序点击顶部导航栏切换样式代码实例
2019/11/12 Javascript
Antd-vue Table组件添加Click事件,实现点击某行数据教程
2020/11/17 Javascript
Vue使用鼠标在Canvas上绘制矩形
2020/12/24 Vue.js
[01:46]2018完美盛典章节片——坚守
2018/12/17 DOTA
django解决订单并发问题【推荐】
2019/07/31 Python
Python绘制动态水球图过程详解
2020/06/03 Python
Python流程控制语句的深入讲解
2020/06/15 Python
python Scrapy框架原理解析
2021/01/04 Python
CSS3 :not()选择器实现最后一行li去除某种css样式
2016/10/19 HTML / CSS
武汉高蓝德国际.net机试
2016/06/24 面试题
畜牧兽医本科生个人的自我评价
2013/10/11 职场文书
初婚未育证明
2014/01/15 职场文书
房地产广告词大全
2014/03/19 职场文书
2014年科技工作总结
2014/11/26 职场文书
通讯稿范文
2015/07/22 职场文书
2015上半年个人工作总结
2015/07/27 职场文书
vue+elementui 实现新增和修改共用一个弹框的完整代码
2021/06/08 Vue.js
Mysql中的触发器定义及语法介绍
2022/06/25 MySQL