理解惰性函数

Posted hencins

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解惰性函数相关的知识,希望对你有一定的参考价值。

先列个通过if判断执行的代码块:
creatXHR()

function createXHR(){
  if (typeof XMLHttpRequest != "undefined"){ // 首先检查内置的XHR
    return new XMLHttpRequest();
  } else if (typeof ActiveXObject != "undefined"){
    // 没有内置XHR就再测试有没有基于ActiveX的XHR
    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];
          break
        } catch (ex){
          // 跳过
        }
      }
    }

    return new ActiveXObject(arguments.callee.activeXString);
  } else { // 都没有发现抛错
    throw new Error("No XHR object available.");
  }
}

这样通过大量if语句将执行引导到正确代码中,但如果浏览器支持内置XHR,它就是一直支持的,这种测试就变的没有必要。

即使只有一个if语句的代码也肯定比没有if语句的慢,所以如果if语句不必每次执行,代码可以运行的更快一些。

可以通过惰性载入来解决:惰性载入表示函数执行的分支仅会发生一次。

有两种实现惰性载入的方式:

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

在第一次调用的过程中该函数会被覆盖为另外一个按合适方式执行的函数,这样任何对原函数的调用都不必再经过执行的分支了:

// 使用惰性载入重写
function createXHR(){
  if (typeof XMLHttpRequest != "undefined"){ // 首先检查内置的XHR
    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];
            break
          } catch (ex){
            // 跳过
          }
        }
      }
    };

    return new ActiveXObject(arguments.callee.activeXString);
  } else { // 都没有发现抛错
    createXHR = function(){
      throw new Error("No XHR object available.");
    };
  }

  return createXHR(); // 再调用一下新赋的函数
}

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

这样做在第一次调用函数时就不会损失性能了,但在代码首次加载时会损失一点性能:

// 创建一个匿名、自执行函数来确定应该使用哪一个函数实现。
var createXHR = (function(){
  if (typeof XMLHttpRequest != "undefined"){ // 首先检查内置的XHR
    return function(){
      return new XMLHttpRequest();
    };
  } else if (typeof ActiveXObject != "undefined"){
    return 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];
            break
          } catch (ex){
            // 跳过
          }
        }
      }
    };

    return new ActiveXObject(arguments.callee.activeXString);
  } else { // 都没有发现抛错
    return function(){
      throw new Error("No XHR object available.");
    };
  }
})();

总结

惰性载入函数优点:只在执行分支代码时牺牲一点儿性能,避免重复执行不必要代码。


以上是关于理解惰性函数的主要内容,如果未能解决你的问题,请参考以下文章

C#函数式编程中的惰性求值详解

Kotlin函数式编程 ③ ( 早集合与惰性集合 | 惰性集合-序列 | generateSequence 序列创建函数 | 序列代码示例 | take 扩展函数分析 )

Kotlin函数式编程 ③ ( 早集合与惰性集合 | 惰性集合-序列 | generateSequence 序列创建函数 | 序列代码示例 | take 扩展函数分析 )

理解 pyspark 中的惰性求值行为

Scala编程之惰性函数

使用惰性执行代码一次 - Swift