最近很多朋友喜欢上设计,但是大家却不知道如何去做,别担心有图老师给你解答,史上最全最棒的详细解说让你一看就懂。
【 tulaoshi.com - Web开发 】
最近在读《JavaScript 设计模式》一书,其中工厂模式中提到了memoizing技术,今天仔细整理了一下memoization 相关的资料,与大家共享。
Memoization的定义:memoization 一词是Donald Michie 根据拉丁语memorandum杜撰的一个词。相应的动词、过去分词、ing形式有memoiz、memoized、memoizing.
(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)Memoization 是一种将函数返回值缓存起来的方法,Memoization 原理非常简单,就是把函数的每次执行结果都放入一个键值对(数组也可以,视情况而定)中,在接下来的执行中,在键值对中查找是否已经有相应执行过的值,如果有,直接返回该值,没有才 真正执行函数体的求值部分。很明显,找值,尤其是在键值对中找值,比执行函数快多了。现代 JavaScript 的开发也已经大量使用这种技术。
一个简单的使用memoization的例子我们知道,在不同的浏览器中,xmlHttpRequest对象的具体实现都不同。需要判断何种浏览器以执行具体的方法。这里就有一个使用memoization来实现的例子。
function createXHRObject = function(){ //先把三个匿名函数缓存起来。 var methods = [ function(){return new XMLHttpRequest();}, function(){return new ActiveXObject("Msxml2.XMLHTTP");}, function(){return new ActiveXObject("Microsoft.XMLHTTP");} ]; for(var i=0,len=methods.length;ilen;i++){ try{//这里用try catch来代替了条件判断,通常我不赞成这种写法 methods[i](); } catch(e){ continue;//如果报异常,则执行下一次循环 } // 把createXHRObject 与能正常执行的匿名函数对应起来,再调用createXHRObject不用再检测浏览器了 createXHRObject = method[i]; return method[i]; } }以上是一个简单的例子,第一次执行createXHRObject()的时候,会循环判断methods 中的方法,获取一个能正确执行的,并将createXHRObject的引用指向这个方法。以后再使用这个方法的时候,不用去判断,直接自动获取正确的方法。这省去了频繁的ajax调用中浏览器的检测。
当然,这个方法看上去效率的提升不是特别明显,我之所以写上来,是因为能比较清晰的理解memoization是如何实现的。在递归调用的时候,memoization的威力才能更好的显现。
一个递归的例子:
function fib(n) { if (n 2) { return n; } return fib(n - 1) + fib(n - 2); }这是一个经典的斐波纳契序列,fib(20) 会把fib这个方法执行21891次,如果是fib(40),这会执行331160281次。
再看看如何使用memoization来实现,
(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/) var iterMemoFib = (function() { var cache = [1, 1]; var fib = function(n) { if (n = cache.length) { //将一个递归转换成了一个 for (var i = cache.length; i = n; i++) { cache[i] = cache[i - 2] + cache[i - 1]; } } return cache[n-1]; } return fib; })();将Function的原型扩展memoize 和unmemoize 方法,这样你可以对任何函数实现memoize和解除memoize,当然,这个方法要慎,对一些不是频繁执行的函数,没必要缓存:
Function.prototype.memoize = function() { var pad = {}; var self = this; var obj = arguments.length 0 ? arguments[i] : null; var memoizedFn = function() { // 把参数作为数组保存,作为键,把函数执行的结果作为值缓存起来 var args = []; for (var i = 0; i arguments.length; i++) { args[i] = arguments[i]; } if (!(args in pad)) { pad[args] = self.apply(obj, arguments); } return pad[args]; } memoizedFn.unmemoize = function() { return self; } return memoizedFn; } Function.prototype.unmemoize = function() { alert("Attempt to unmemoize an unmemoized function."); return null; }使用方法:
fib.memoize();参考文档:
Memoizing functions in JavaScript JavaScript Memoization 提升JS性能:将递归转换为迭代 MemoizationFrom Wikipedia, the free encyclopedia来源:http://www.tulaoshi.com/n/20160220/1632906.html
看过《JavaScript工厂模式的memoizing技术》的人还看了以下文章 更多>>