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

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.存储变量
3.封装私有变量

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

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,然后通过闭包对齐操作

解决循环错误的问题

我们先来看代码


        
        
        
    
    
    

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


        
        
        
    
    
    

当for循环的时候,自执行函数就会执行(匿名自执行函数的最大特点就是创建闭包)

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

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

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

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

let和闭包的关系

同样是这个问题


        
        
        
    
 
 

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


        
        
        
    
 
 

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

闭包的优缺点

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

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

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

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

你可能感兴趣的:(javascript深入理解系列——(六)闭包)