JS---memoizing技术

memoizing技术

Memoization介绍

是一种将函数返回值缓存起来的方法

原理:

就是把函数的每次执行结果都放入一个键值对/数组中,在接下来的执行中,在键值对中查找是否已经有相应执行过的值,如果有,直接返回该值,没有才执行函数体的求值部分

优点:

在键值对中找值,比执行函数快多了。

  •  一个简单的使用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;i<len;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实现

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() {
   return null;
}

使用方法:

fib.memoize();

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值