// memoize: 使用memoization來(lái)緩存的通用方法
// func: 要被緩存的方法
// context: 方法 " /> 国产一区二区精品丝袜,亚洲成人精品,日韩一区二区三区免费观看

中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

Javascript Memoizer淺析

以下來(lái)自John Hann的實(shí)現(xiàn),這段代碼引起了我的注意,它用巧妙的方法把方法調(diào)用的結(jié)果緩存起來(lái)了。

代碼解析:

復(fù)制代碼 代碼如下:
// memoize: 使用memoization來(lái)緩存的通用方法
// func: 要被緩存的方法
// context: 方法執(zhí)行上下文
// Note: 方法必須是外部可訪(fǎng)問(wèn)的,參數(shù)是可字符序列化的
function memoize (func, context) {
    function memoizeArg (argPos) { //參數(shù)表示原始方法中參數(shù)的位置
        var cache = {}; //這個(gè)緩存的key是參數(shù),value是執(zhí)行結(jié)果
        return function () { //返回一個(gè)函數(shù)閉包
            if (argPos == 0) { //第一個(gè)參數(shù),如果參數(shù)在緩存的key中不存在,就執(zhí)行原始函數(shù)并且存儲(chǔ)執(zhí)行結(jié)果
                if (!(arguments[argPos] in cache)) {
                    cache[arguments[argPos]] = func.apply(context, arguments);
                }
                return cache[arguments[argPos]];
            }
            else { //不是第一個(gè)參數(shù),如果參數(shù)在緩存的key中不存在,就遞歸執(zhí)行memoizeArg方法,原始方法中參數(shù)的位置-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參數(shù)的長(zhǎng)度,Javascript中用length屬性,其它的用arity屬性
    return memoizeArg(arity - 1); //從最后一個(gè)參數(shù)開(kāi)始遞歸
}

使用:
復(fù)制代碼 代碼如下:
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));

看似簡(jiǎn)單,再一看好像也并不易懂,可是如果能對(duì)閉包的使用比較熟悉的話(huà),就很好理解了。經(jīng)過(guò)上面幾次mem.call的調(diào)用之后,形成的是一棵樹(shù),每個(gè)節(jié)點(diǎn)都是一個(gè)閉包,每個(gè)閉包內(nèi)有一個(gè)cache,每個(gè)cache的key都是樹(shù)分支:

(注:上面圖中的“結(jié)果”也是一個(gè)閉包,只不過(guò)argPos為0而已)

不過(guò)方法有諸多,比如limboy說(shuō):

復(fù)制代碼 代碼如下:
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];
    };
}

實(shí)現(xiàn)更簡(jiǎn)易,不過(guò)把參數(shù)push到一個(gè)數(shù)組內(nèi),再把數(shù)組當(dāng)key,而key是只支持字符串型的,因此這點(diǎn)在使用上需要注意(比如一個(gè)對(duì)象tostring之后可能只看到”[object Object]“了),它的功能比上面那個(gè)要弱一些。

改進(jìn)這一點(diǎn)也不難,把參數(shù)另立一個(gè)對(duì)象即可,而原cache對(duì)象和這個(gè)另立的參數(shù)對(duì)象使用一個(gè)ID關(guān)聯(lián)起來(lái):

復(fù)制代碼 代碼如下:
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];
    };
}

還有一些其他的辦法,都可以寫(xiě)成簡(jiǎn)潔的函數(shù)式方法。

JavaScript技術(shù)Javascript Memoizer淺析,轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 日韩欧美一区二区三区免费观看 | 中文字幕一区二区三区四区 | 伊人春色成人网 | www日本在线 | 97精品超碰一区二区三区 | 色精品视频 | 亚洲综合日韩精品欧美综合区 | 免费欧美视频 | 久久精品免费 | 亚洲免费在线观看 | 伊人最新网址 | 久久乐国产精品 | 精品国产乱码一区二区三区 | 天天草天天 | 国产美女视频黄a视频免费 国产精品福利视频 | 久久国产精品一区二区三区 | 欧美午夜精品久久久久久浪潮 | 夜夜爽99久久国产综合精品女不卡 | 欧美日韩一区二区视频在线观看 | 久久久青草婷婷精品综合日韩 | 一区二区三区av | aaaa网站 | 欧美激情综合五月色丁香小说 | 日韩在线免费视频 | 久久国产成人精品国产成人亚洲 | 精品精品视频 | 九九热这里| 日韩在线一区视频 | 国内精品久久久久久 | 精品亚洲一区二区三区 | 天天插天天干 | 欧美成年网站 | 日韩精品无码一区二区三区 | 草比网站 | 亚洲永久在线 | 手机av免费在线 | 久久aⅴ乱码一区二区三区 亚洲欧美综合精品另类天天更新 | 精品国产18久久久久久二百 | 99热播精品| 久久国产精品一区二区 | 亚洲视频a|