• 读书笔记:javascript高级技巧(二)


    四。惰性载入函数

    因为浏览器兼容的原因,我们的javascript代码会有大量的if语句,将执行引导到正确的代码中,看如下函数:

     function createXHR(){
          if (typeof XMLHttpRequest != "undefined"){                
                  return new XMLHttpRequest();                
          } else if (typeof ActiveXObject != "undefined"){                                 
                  if (typeof arguments.callee.activeXString != "string"){
                      var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                      "MSXML2.XMLHttp"],
                          i, len;
              
                      for (i=0,len=versions.length; i < len; i++){
                          try {
                              new ActiveXObject(versions[i]);
                              arguments.callee.activeXString = versions[i];
                          } catch (ex){
                              //skip
                          }
                      }
                  }                
                  return new ActiveXObject(arguments.callee.activeXString);                
          } else {               
                  throw new Error("No XHR object available.");               
          }      
     }

    每次在调用createXHR时,都要对浏览器支持的能力进行检查。如果多次调用,这种检查就没有必要了。如果if语句不必每次执行,那么代码可以运行的更快一些。解决方案就是称之为惰性载入的技巧。
    惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式。第一种就是在函数被调用时再处理函数:在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式执行的函数,这样任何对原函数的调用都不用再经过执行分支。第二种是在声明函数时就指定适当的函数:这样第一次调用时就不会损失性能力,而在代码首次加载时会损失一点性能。具体看码~

    1.在函数被调用时再处理函数

    function createXHR(){
                if (typeof XMLHttpRequest != "undefined"){
                    createXHR = function(){
                        return new XMLHttpRequest();
                    };
                } else if (typeof ActiveXObject != "undefined"){
                    createXHR = function(){                    
                        if (typeof arguments.callee.activeXString != "string"){
                            var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
                                            "MSXML2.XMLHttp"],
                                i, len;
                    
                            for (i=0,len=versions.length; i < len; i++){
                                try {
                                    new ActiveXObject(versions[i]);
                                    arguments.callee.activeXString = versions[i];
                                } catch (ex){
                                    //skip
                                }
                            }
                        }
                    
                        return new ActiveXObject(arguments.callee.activeXString);
                    };
                } else {
                    createXHR = function(){
                        throw new Error("No XHR object available.");
                    };
                }
                
                return createXHR();
            }
            
            var xhr1 = createXHR();
            var xhr2 = createXHR();

     在第一次调用函数时会再处理函数,根据不同条件重写函数,这样在以后的调用中会直接调用新重写的函数而不用经过重重判断。   

    2.在声明函数时就指定适当的函数

     1 var createXHR = (function(){
     2             if (typeof XMLHttpRequest != "undefined"){
     3                 return function(){
     4                     return new XMLHttpRequest();
     5                 };
     6             } else if (typeof ActiveXObject != "undefined"){
     7                 return function(){                    
     8                     if (typeof arguments.callee.activeXString != "string"){
     9                         var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
    10                                         "MSXML2.XMLHttp"],
    11                             i, len;
    12                 
    13                         for (i=0,len=versions.length; i < len; i++){
    14                             try {
    15                                 new ActiveXObject(versions[i]);
    16                                 arguments.callee.activeXString = versions[i];
    17                                 break;
    18                             } catch (ex){
    19                                 //skip
    20                             }
    21                         }
    22                     }
    23                 
    24                     return new ActiveXObject(arguments.callee.activeXString);
    25                 };
    26             } else {
    27                 return function(){
    28                     throw new Error("No XHR object available.");
    29                 };
    30             }
    31         })();
    32         
    33         var xhr1 = createXHR();
    34         var xhr2 = createXHR();
     //自执行匿名函数语法:(function(){})()  最开始看不懂这高大上的写法,原来是自执行函数~~~

    这种方式类似于第一种,思路水样的,不同的就是第一行代码,新增了自执行的匿名函数,另外每个分支都返回正确的函数定义,以便立即将其复制给createXHR()。

    五。函数柯里化

    在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家哈斯凯尔·加里命名的,尽管它是 Moses Schönfinkel 和 Gottlob Frege 发明的。

    这是来自维基百科的名词解释。顾名思义,柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围。

    理解起来比较困难,下面看实例:

    function curry(fn){
                var args = Array.prototype.slice.call(arguments, 1); //获取第一个参数之后的所有参数
                return function(){
                    var innerArgs = Array.prototype.slice.call(arguments),   //获取内部函数的所有参数
                        finalArgs = args.concat(innerArgs);               //组合
                    return fn.apply(null, finalArgs);            //没有考虑到执行环境,所以apply()第一个参数为null
                };
            }
        
            function add(num1, num2){
                return num1 + num2;
            }
            
            var curriedAdd = curry(add, 5);   //创建了第一个参数绑定为5的柯里化版本
            alert(curriedAdd(3));   //8       //传入第二个参数,调用add方法,相当于add(5,3)
    
            var curriedAdd2 = curry(add, 5, 12);
            alert(curriedAdd2());   //17

    函数柯里化还常常作为函数绑定的一部分包含在其中,构造出更为复杂的bind()函数;

    function bind(fn, context){
                var args = Array.prototype.slice.call(arguments, 2);
                return function(){
                    var innerArgs = Array.prototype.slice.call(arguments),
                        finalArgs = args.concat(innerArgs);
                    return fn.apply(context, finalArgs);
                };
            }
        
            var handler = {
                message: "Event handled",
            
                handleClick: function(name, event){
                    alert(this.message + ":" + name + ":" + event.type);
                }
            };
            
            var btn = document.getElementById("my-btn");
            EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "my-btn"));
  • 相关阅读:
    JSP基础语法
    Tomcat服务器的安装及配置
    数据库连接失败出现4064错误
    错误页跳转
    Eclipse配置jstl标准标签库详解
    tomcat文件目录结构及功能介绍
    警告: [SetPropertiesRule]{Context/Loader} Setting property 'useSystemClassLoaderAsParent' to 'false' did not find a matching property.
    tomcat:A docBase * inside the host appBase has been specifi, and will be ignored
    Prim算法
    (值类型引用类型)和null的关系
  • 原文地址:https://www.cnblogs.com/mopagunda/p/4646847.html
Copyright © 2020-2023  润新知