zoukankan      html  css  js  c++  java
  • memoize使用实例之创建XHR

    首先看看创建XHR最简单的方法:

    function createXHR() { // Factory method.  
        var methods = [  
            function() { return new XMLHttpRequest(); },  
            function() { return new ActiveXObject('Msxml2.XMLHTTP'); },  
            function() { return new ActiveXObject('Microsoft.XMLHTTP'); }  
        ];  
        var xhr;  
        for (var i = 0, len = methods.length; i < len; i++) {  
            try {  
                xhr = methods[i]();  
            } catch(e) {  
                continue;  
            }  
            // If we reach this point, method[i] worked.  
            return xhr;  
        }  
        throw new Error('Could not create an XHR object.');  
    }  
    

    我们调用createXHR函数来发起一个ajax请求,该函数会在内部遍历查找当前浏览器可用的xhr类型,然后返回。但显然每次都要循环一遍是没有必要的,能否让函数记住上一次返回的结果呢。

     在Pro Javascript design patterns一书里,可以看到这样的解决方法:

    function createXHR2() {  
        var methods = [  
            function() { return new XMLHttpRequest(); },  
            function() { return new ActiveXObject('Msxml2.XMLHTTP'); },  
            function() { return new ActiveXObject('Microsoft.XMLHTTP'); }  
        ];  
        var xhr  
        for (var i = 0, len = methods.length; i < len; i++) {  
            try {  
                xhr = methods[i]();  
            } catch(e) {  
                continue;  
            }  
            createXHR2 = function() {// cache it  
                return xhr;  
            }  
            return methods[i];  
        }  
        throw new Error('Could not create an XHR object.');  
    }  
    

    可以看到14行的作用是,在函数第一次执行之后,把函数自身给替换了,当函数第二次执行时,直接就是return xhr;,这种做法使得函数具有了记忆功能。

     很巧妙的做法,但这样做的代价是,让一个函数多实现了一个它本不该有的功能,即cache功能,对于函数功能单一性的原则说,这种做法算不上完美。

     可能经常会碰到这种需要记忆的函数,这种机制需要被抽象出来:

    (以下代码来源于 Memoization in JavaScript,略有改动)

    function asArray(quasiArray, start) {  
        var r = [];  
        for (var i = (start || 0); i < quasiArray.length; i++)  
            r.push(quasiArray[i]);  
        return r;  
    }  
      
    Function.prototype.memoize = function(scope) {  
        var cache  = {};  
        var self = this;  
        scope = scope !== undefined ? scope : null;  
      
        var memoizedFn = function() {  
            var key = asArray(arguments).toString();  
      
            if (!(key in cache)) {  
                cache[key] = self.apply(scope, arguments);  
            }  
      
            return cache[key];  
        };  
      
        memoizedFn.unmemoize = function() {  
            return self;  
        };  
      
        return memoizedFn;  
    };  
    

    注:arguments是类似数组的东东,有部分数组特性,比如arguments[0],但没有toString()之类数组内置方法,所以需要用asArray将其转换为数组。

    var memoizedCreateXHR = createXHR.memoize();  
      
    console.info(memoizedCreateXHR());  
    

    关于memoization的更多应用,可以参考

    speed-up-your-javascript-part-2/

    One-Line JavaScript Memoization

    Timed Memoization 

  • 相关阅读:
    JAVA调用WCF
    写代码之前要做什么?
    漫谈界面和数据
    UIButton 简易的UI
    数据结构利器之私房STL(中)
    有趣的位运算
    基于TCP的C/S初级网络编程1
    数据结构利器之私房STL(上)
    Unix/Linux 那些系统启动后的进程
    【字符串匹配】KMP算法之道
  • 原文地址:https://www.cnblogs.com/aj3423/p/3150514.html
Copyright © 2011-2022 走看看