项目中需要用到 大计算量 耗时的js运算。
Memoize 是一个优化方法 ,对耗时的递归运算,漫长的查找运算的结果进行缓存,使运行时间最小化
原理是缓存先前的结果计算值从而可以避免需要重新计算 提高运行速度的方法。
magic 先看效果
以斐波那契数组 为例
当n>40 firfox ie 都会弹出停止脚本的提示框,浏览器进入僵死状态,ui线程被阻塞
var fibonacci =function(n) { return n <2? n : arguments.callee(n -1) + arguments.callee(n -2); }; console.log(fibonacci (40))
著名underscore 的 Memoize 方法, 成功执行 没有僵死,ui线程没有阻塞
var fibonacci = _.memoize(function(n) { return n <2? n : arguments.callee(n -1) + arguments.callee(n -2); }); document.write( fibonacci (40))
源码分析
_.memoize = function(func, hasher) { var memoize = function(key) { var cache = memoize.cache; var address = hasher ? hasher.apply(this, arguments) : key; if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); return cache[key]; }; memoize.cache = {}; return memoize; };
以参数作为键进行缓存,被执行的结果按参数缓存在memo对象上,用内存空间 换cpu执行时间
详解 :
Example1 :
function square(num){ return num*num; } square(10) //100
square(100)
如上所示,每次调用square方法,都会重新计算。如果这是一个递归 耗时的任务 缓存就很重要可以很好的优化执行时间。 如下所示
function square(num){ var result = ''; if(!square.cache[num]){ console.log("Computing value..."); result = num*num; square.cache[num] = result; } return square.cache[num]; } square.cache = {} square(10) //第一次调用 计算结果 缓存结果 square(10) //第二次开始从缓存中返回结果。 square(20) // 如果一个新值,再次计算。
创建一个普通的js对象,以参数作为键,缓存结果存在键值上.
Example2 (升级)
square的arguments,可能是数组或者json对象
var square = function(num){ var key = JSON.stringify(Array.prototype.slice.call(num)); if(!square.cache[key]){ var result={}; //Computation console.log("Computing value..."); result = num*num; square.cache[key] = result; } return square.cache[key]; } square.cache = {};
缓存是个很好的优化js执行速度的方法,不但可以缓存数据运算的结果,前端用到最多的是类似backbone一类mvc 前端框架,缓存视图对象的实例。