<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        JavaScriptMemoization讓函數也有記憶功能_javascript技巧

        來源:懂視網 責編:小采 時間:2020-11-27 21:01:17
        文檔

        JavaScriptMemoization讓函數也有記憶功能_javascript技巧

        JavaScriptMemoization讓函數也有記憶功能_javascript技巧:比如說,我們想要一個遞歸函數來計算 Fibonacci 數列。一個 Fibonacci 數字是之前兩個 Fibonacci 數字之和。最前面的兩個數字是 0 和 1。 代碼如下: var fibonacci = function (n) { return n }; for (var i = 0; i doc
        推薦度:
        導讀JavaScriptMemoization讓函數也有記憶功能_javascript技巧:比如說,我們想要一個遞歸函數來計算 Fibonacci 數列。一個 Fibonacci 數字是之前兩個 Fibonacci 數字之和。最前面的兩個數字是 0 和 1。 代碼如下: var fibonacci = function (n) { return n }; for (var i = 0; i doc

        比如說,我們想要一個遞歸函數來計算 Fibonacci 數列。一個 Fibonacci 數字是之前兩個 Fibonacci 數字之和。最前面的兩個數字是 0 和 1。
        代碼如下:
        var fibonacci = function (n) {
        return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
        };

        for (var i = 0; i <= 10; i += 1) {
        document.writeln('// ' + i + ': ' + fibonacci(i));
        }

        // 0: 0
        // 1: 1
        // 2: 1
        // 3: 2
        // 4: 3
        // 5: 5
        // 6: 8
        // 7: 13
        // 8: 21
        // 9: 34
        // 10: 55

        這樣是可以工作的,但是它做了很多無謂的工作。 Fibonacci 函數被調用了 453 次。我們調用了 11 次,而它自身調用了 442 次去計算可能已經被剛計算過的值。如果我們讓該函數具備記憶功能,就可以顯著地減少它的運算量。

        我們在一個名為 memo 的數組里保存我們的儲存結果,儲存結果可以隱藏在閉包中。當我們的函數被調用時,這個函數首先看是否已經知道計算的結果,如果已經知道,就立即返回這個儲存結果。
        代碼如下:
        var fibonacci = function() {
        var memo = [0, 1];
        var fib = function (n) {
        var result = memo[n];
        if (typeof result !== 'number') {
        result = fib(n - 1) + fib(n - 2);
        memo[n] = result;
        }
        return result;
        };
        return fib;
        }();

        這個函數返回同樣的結果,但是它只被調用了 29 次。我們調用了它 11 次,它自身調用了 18 次去取得之前儲存的結果。
        以上內容來自:http://demon.tw/programming/javascript-memoization.html

        realazy在blog上給出了一個JavaScript Memoization的實現,Memoization就是函數返回值的緩存,比如一個函數參數與返回結果一一對應的hash列表,wiki上其實也有詳細解釋,我不細說了,只討論一下具體實現的問題,realazy文中的代碼有一些問題,比如直接用參數拼接成的字符串作為查詢緩存結果的key,如果參數里包括對象或數組的話,就很難保證唯一的key,還有1樓評論里提到的:[221,3]和[22,13]這樣的參數也無法區分。
        那么來改寫一下,首先還是用hash表來存放緩存數據:

        代碼如下:
        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];
        };
        }

        嗯,區別是直接把數組當作鍵來用,不過要注意函數里的arguments是js解釋器實現的一個特殊對象,并不是真正的數組,所以要轉換一下……
        ps: 原來的參數包括方法名稱和上下文引用:fib.fib_memo = Memoize(‘fib_memo', fib),但實際上currying生成的函數里可以用this直接引用上層對象,更復雜的例子可以參考John Resig的makeClass,所以我改成直接傳函數引用:fib.fib_memo = Memoize(fib.fib_memo)
        這樣寫看上去似乎很靠譜,由參數組成的數組不是唯一的么。但實際上,數組之所以能作為js對象的屬性名稱來使用,是因為它被當作字符串處理了,也就是說如果你給函數傳的參數是這樣:(1,2,3), cache對象就會是這個樣子:{ “1,2,3″: somedata },如果你的參數里有對象,比如:(1,2,{i:”yy”}),實際的鍵值會是:”1,2,[object Object]“,所以這跟把數組拼接成字符串的方法其實沒有區別……
        示例:
        代碼如下:
        var a = [1,2,{yy:'0'}];
        var b = [1,2,{xx:'1'}];
        var obj = {};
        obj[a] = "111";
        obj[b] = "222";
        for( var i in obj )
        alert( i + " = " + obj[i] ); //只會彈出"1,2,[object Object] = 222",obj[a] = "111"被覆蓋了

        直接用參數作為鍵名的方法不靠譜了…………換一種方法試試:
        代碼如下:
        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];
        };
        }

        可以完全避免上述問題,沒有使用hash的鍵值對索引,而是把函數的參數和結果分別緩存在兩個列表里,每次都先遍歷整個參數列表作比較,找出對應的鍵名/ID號之后再從結果列表里取數據。以下是比較數組的equal方法:
        代碼如下:
        function equal( first, second ){
        if( !first || !second || first.constructor != second.constructor )
        return false;
        if( first.length && typeof first != "string" )
        for(var i=0, l = ( first.length > second.length ) ? first.length : second.length; iif( !equal( first[i], second[i] ) ) return false;
        }
        else if( typeof first == 'object' )
        for(var n in first){
        if( !equal( first[n], second[n] ) ) return false;
        }
        else
        return ( first === second );
        return true;
        }

        千萬不要直接用==來比較arguments和args里的數組,那樣比較的是內存引用,而不是參數的內容。
        這種方法的速度很慢,equal方法其實影響不大,但是緩存的結果數量多了以后,每次都要遍歷參數列表卻是很沒效率的(求80以上的fibonacci數列,在firefox3和safari3上都要40ms左右)
        如果在實際應用中參數變動不多或者不接受參數的話,可以參考Oliver Steel的這篇《One-Line JavaScript Memoization》,用很短的函數式風格解決問題:
        代碼如下:
        function Memoize(o, p) {
        var f = o[p], mf, value;
        var s = function(v) {return o[p]=v||mf};
        ((mf = function() {
        (s(function(){return value})).reset = mf.reset;
        return value = f.apply(this,arguments); //此處修改過,允許接受參數
        }).reset = s)();
        }

        示例:
        代碼如下:
        var fib = {
        temp: function(n){
        for(var i=0;i<10000;i++)
        n=n+2;
        return n;
        }
        }
        Memoize(fib,"temp"); //讓fib.temp緩存返回值
        fib.temp(16); //執行結果:20006,被緩存
        fib.temp(20); //執行結果:20006
        fib.temp(10); //執行結果:20006
        fib.temp.reset(); //重置緩存
        fib.temp(10); //執行結果:20010

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        JavaScriptMemoization讓函數也有記憶功能_javascript技巧

        JavaScriptMemoization讓函數也有記憶功能_javascript技巧:比如說,我們想要一個遞歸函數來計算 Fibonacci 數列。一個 Fibonacci 數字是之前兩個 Fibonacci 數字之和。最前面的兩個數字是 0 和 1。 代碼如下: var fibonacci = function (n) { return n }; for (var i = 0; i doc
        推薦度:
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲人成电影亚洲人成9999网 | 色欲aⅴ亚洲情无码AV| 永久免费观看黄网站| 日韩成全视频观看免费观看高清| 免费无遮挡无码永久在线观看视频| 免费jjzz在线播放国产| 亚洲成av人在线观看网站 | 亚洲免费观看视频| 国产成人亚洲精品狼色在线| av电影在线免费看| 九月丁香婷婷亚洲综合色| 日本视频免费高清一本18| 亚洲精品中文字幕无码AV| 亚洲三级高清免费| 亚洲第一成年网站视频| 亚洲VA综合VA国产产VA中| 一本到卡二卡三卡免费高| 亚洲毛片αv无线播放一区| 男女午夜24式免费视频| 亚洲天堂视频在线观看| 亚色九九九全国免费视频| 亚洲成av人片天堂网无码】| 免费人成网站7777视频| 中国在线观看免费的www| 久久亚洲精品中文字幕无码| 国产卡一卡二卡三免费入口| 在线观看亚洲免费视频| 亚洲午夜久久久影院| 亚洲黄色免费网址| 国产精品亚洲专区无码不卡| 亚洲av无码专区在线播放| 亚色九九九全国免费视频| 边摸边吃奶边做爽免费视频99| 国产成人A在线观看视频免费| 亚洲深深色噜噜狠狠爱网站| 91精品手机国产免费| 亚洲高清一区二区三区电影| 国产亚洲精品拍拍拍拍拍| 无码国产精品一区二区免费式影视 | 亚洲av永久无码精品三区在线4| 国产特黄一级一片免费|