美文网首页
JavaScript - 闭包函数

JavaScript - 闭包函数

作者: 尤雨溪的大迷弟 | 来源:发表于2019-06-03 22:12 被阅读0次

    什么是闭包函数?

    概念:闭包是指有权限访问上一级父作用域的变量的函数。本质:在一个作用域范围内嵌套了函数。

    function fn1(){
        function fn(){}
        return fn;
    }
    

    这种函数的嵌套方式就是闭包函数,这种模式的好处是可以让内层函数访问到外层函数的变量,并且让函数整体不至于因为函数的执行完毕而被销毁。
    比如下面的代码,随着函数的每次执行,变量的值都会进行递增1,原因是因为外层函数的变量处于内层函数的作用域链当中,被内层函数所使用着,当js垃圾回收机制读取到这一情况后就不会进行垃圾回收。

    function fn1(){
        var a = 1;
        function fn(){
            a++;
            console.log(a);
        }
        return fn;
    }
    // 调用函数
    var x  = fn1();
    x(); // 2
    x();// 3
    //需要用一个变量承接,不然每次fn1()()都相当于重新调用
    fn1()();// 2
    fn1()();// 2
    

    闭包函数在js的开发当中是非常常见的写法,例如下面这种写法,功能是实现了对数组的一些常规操作的封装,也是属于对闭包函数的一种应用。

    let Utils = (function(){
        var list = [];
        return {
            add:function(item){
                if(list.indexOf(item)>-1) return; // 如果数组内元素存在,那么不在重复添加
                list.push(item);
            },
            remove:function(item){
                if(list.indexOf(item) < 0) return; // 如果要删除的数组数组之内不存在,那么就返回
                list.splice(list.indexOf(item),1);
            },
            get_length:function(){
                return list.length;
            },
            get_showData:function() {
                return list;
            }
        }
    })();
    Utils.add("hello,world");
    Utils.add("this is test");
    console.log(Utils.get_showData());// ["hello,world","this is test"]
    

    立即执行函数(IIFE)

    这种自调用的写法本质上来讲也是一个闭包函数。
    在js开发中,经常碰到立即执行函数的写法。大体如下:

    // 下面的这种写法就是立即执行函数
    // 在函数内部的内容会自动执行
    (function(){
        var a = 10;
        var b = 20;
        console.log(a+b); // 30
    })();
    //括号也可写到里面
    (function(){
    var a = 10;
    var b = 20;
    console.log(a+b);//30
    }());
    

    我们可以通过第二个括号来传入参数:

    (function(i){
        console.log(i);
    })(i);
    

    通过这种闭包函数,我们可以有效的避免变量污染等问题,从而创建一个独立的作用域。

    但是问题相对来说也很明显,就是在这个独立的作用域当中,我们没有办法将其中的函数或者变量让外部访问的到。所以如果我们在外部需要访问这个立即执行函数中的变量或者方法,我们就需要通过第二个括号将window这个全局的变量对象传入,并且将需要外部访问的变量或者函数赋值给window,这样做相当于将其暴露在了全局的作用域范围之内。

    需要注意的是,通常情况下我们只需要将必要的方法暴露,这样才能保证代码并不会相互产生过多的影响,从而降低耦合度。
    例如:

        (function (window) {
            var a = 10; // 私有属性
            function show() {
                return a++;
            }
            function sayHello() { // 私有方法
                alert("hello,world");
            }
            window.show = show;// 将show方法暴露在外部
        })(window);
        console.log(window.show());// 10
        console.log(window.show());// 11
    

    可以自己添加一些自定义的window属性,例如:

        (function(window) {
            function ace(b){
                alert(b);
                console.log(b);
            }
            window.ace = ace;
        })(window);
        window.ace('haha');//弹窗haha,且控制台输出haha
    

    需要注意的是,在很多的代码中,总是在(function(){})()的最前面加上一个 ; 目的是为了防止合并(上线压缩)代码的时候js将代码解析成(function(){})()(function(){})()这种情况。

    相关文章

      网友评论

          本文标题:JavaScript - 闭包函数

          本文链接:https://www.haomeiwen.com/subject/jxcutctx.html