闭包应用-制造惰性函数

273 阅读1分钟

基本概念

惰性函数是函数式编程的一个重要概念。可以有效提高程序的运行效率。 惰性函数表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不会在经过执行的分支了。

如何实现计算缓存

斐波那契数列使用递归计算大数字时,性能会非常低,另外递归造成了大量的重复计算(很多函数执行了多次)

        const temp=[0,1]
        function fibonacci(n){
            if(temp[n]==undefined){
                temp[n]=fibonacci(n-1)+fibonacci(n-2)
            }
            return temp[n]
        }

以上代码虽然实现功能,但是最大的问题就是缓存需要定义一个全局变量。其实这个全局变量是可以隐藏的

使用闭包隐藏全局变量

        const fibonacci = (function () {
            const temp = [0, 1]
            return function (n) {
                if (temp[n] == undefined) {
                    temp[n] = fibonacci(n - 1) + fibonacci(n - 2)
                }
                return temp[n]
            }
        })()

惰性函数还能做什么

单例模式

单例模式是设计模式之一,它保证了一个类只有一个实例。实现方法一般是先判断实例是否存在,如果存在就直接返回,否则就创建了在返回。单例模式的好处就是避免了重复实例化带来的内存开销。

// 单例模式
function Singleton(){
  this.data = 'singleton';
}
​
Singleton.getInstance = (function () {
  var instance;
    
  return function(){
    if (instance) {
      return instance;
    } else {
      instance = new Singleton();
      return instance;
    }
  }
})();
​
var sa = Singleton.getInstance();
var sb = Singleton.getInstance();
console.log(sa === sb); // true
console.log(sa.data); // 'singleton'

单例模式前端最典型的应用场景,全局唯一消息框

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .model {
            width: 200px;
            height: 200px;
            border: 1px solid aqua;
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            text-align: center;
        }
    </style>
</head><body>
    <div id="loginBtn">点我</div>
    <script>
        var getSingle = function (fn) {
            var result; //缓存实例
            return function () {
                return result || (result = fn.apply(this, arguments))
            }
        }
        var createLoginLayer = function () {
            var oDiv = document.createElement("div");
            oDiv.innerHTML = "我是登录浮窗";
            oDiv.className = "model";
            oDiv.style.display = "none";
            document.body.appendChild(oDiv);
            return oDiv;
        }
        var createSingleLoginLayer = getSingle(createLoginLayer);
        document.getElementById("loginBtn").onclick = function () {
            //动态创建弹窗
            //新建一个弹窗实例,内部使用单例模式管理,一直只能有一个.
            var loginLayer = createSingleLoginLayer();
            loginLayer.style.display = "block"
        }
    </script>
</body>