美文网首页
javascript深入理解系列——(六)闭包

javascript深入理解系列——(六)闭包

作者: 悦者生存 | 来源:发表于2018-09-08 22:02 被阅读9次

    javascript深入理解系列文章网址
    https://www.jianshu.com/p/451eed9094f5

    闭包真是面试80%会问到的问题

    闭包的概念

    简单来说能够读取其他函数内部变量的函数

    怎么来理解这句话呢,我们都知道函数内可以读取外部的变量,但是函数外无法读取函数内部的变量
    那么怎么才能做到读取函数内部的变量呢,我们可以在函数内部再定义一个函数,用这个函数读取函数内部的变量,然后最后返回里面这个函数执行的结果,我们就可以得到函数内部的变量了

            function Out(){
                var a=678;
                function In(){
                    console.log(a);
                }
                return In;
            }
            var result=Out();
            result();//678
    

    那么闭包有什么用呢

    1.可以读取函数内部的变量
    2.让这些变量的值始终保持在内存中,不会在调用后被自动清除。

    那我们什么时候用到闭包的?

    1、通过闭包来封装私有方法

    学过java的同学都知道,java可以在类里面写私有变量和方法,外面无法调用,其实在js里面也能实现的,怎么实现那就需要闭包了

    var fn=(function(){
            var counter=0;
            function getValue(val){
                counter+=val;
            }
            return {
                increment:function(){
                    getValue(1);
                },
                decrement:function(){
                    getValue(-1);
                },
                value:function(){
                    return counter;
                }
            }
        })();
        console.log(fn.value());//输出0
        fn.increment();
        console.log(fn.value());//输出1
    

    学过java的同学看到这个是不是很熟悉,像不像java里的面向对象,这里面的increment,decrement,value就相当于闭包,我们可以封装私有变量counter,然后通过闭包对齐操作

    解决循环错误的问题

    我们先来看代码

    <body>
            <button>0</button>
            <button>1</button>
            <button>2</button>
        </body>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
        <script>
            
            for(var i=0;i<$("button").length;i++){
                $("button").eq(i).click(function(){
                    console.log(i);//输出结果总是3
                });
            }
        </script>
    

    上面我们定义了三个按钮,原计划点击相应的按钮,打印相应的文字,但是我们像如上的写法输出后每次的结果都是3,为什么呢,因为我们定义的这些函数不是立即执行函数,而是点击的时候才会执行,可是当我们点击的时候,循环已经结束,i为3,所以我们输出的值都为3。如何解决呢,这就要使用闭包了

    <body>
            <button>1</button>
            <button>2</button>
            <button>3</button>
        </body>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
        <script>
            
            for(var i=0;i<$("button").length;i++){
                (function(val){
                    $("button").eq(val).click(function(){
                    console.log(val);
                    });
                })(i);
                
            }
        </script>
    

    当for循环的时候,自执行函数就会执行

     $("button").eq(val).click(function(){
                    console.log(val);
                    });
    

    而val值是从外面传过来,里面的闭包就会记住每一次的值,存在内存中,每一次的

     $("button").eq(val).click(function(){
                    console.log(val);
                    });
    

    都是互相独立的,所以每一次输出的值互不相同

    let和闭包的关系

    同样是这个问题

    <body>
            <button>0</button>
            <button>1</button>
            <button>2</button>
        </body>
     <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
     <script>
            for(var i=0;i<$("button").length;i++){
                $("button").eq(i).click(function(){
                    console.log(i);//输出结果总是3
                });
            }
        </script>
    

    之所以输出结果总是为3,是因为js只有全局作用域和函数级作用域,当点击的时候就会调用全局作用域i,i为3,所以我们可以使用es6的语法let去添加块级作用域

    <body>
            <button>0</button>
            <button>1</button>
            <button>2</button>
        </body>
     <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
     <script>
            for(let i=0;i<$("button").length;i++){
                $("button").eq(i).click(function(){
                    console.log(i);
                });
            }
        </script>
    

    只要把var改成let就可以,就有了块级作用域,每次点击button的时候都访问其内部的i变量,也就可以解决上面的问题

    闭包的优缺点

    优点:加强封装性,可以达到对变量的保护作用

    缺点:1由于闭包内部变量优先级高于外部变量,所以多查找作用域链中的一个层次,就会在一定程度上影响查找速度
    2.内存的浪费
    如何避免浪费使父级函数=null;

    参考
    https://juejin.im/post/5aa90e5ef265da239f0713a1#heading-5

    https://wangdoc.com/javascript/basic/index.html

    相关文章

      网友评论

          本文标题:javascript深入理解系列——(六)闭包

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