温故知新-闭包

71 阅读2分钟

以前自己也花过时间去啃那本厚厚的《JS权威指南》不过看的那叫一个晕啊,云里雾里的,经过这么久的实践也算是有了一些自己的小理解吧,有不对的地方还请jym指正。

什么是闭包

简单的来说通过一个函数返回另一个函数就是闭包

function bibao () {
    let str = 1;
    return function () {
        return '我是返回的函数' + str++
    }
}

像上面这几行简单的代码就生成了一个闭包。 我们可以看到通过 return 返回另外一个函数。既然返回了一个函数,这个函数有什么用呢?

image.png 通过控制台打印的信息可以看到,我们通过调用返回的函数获取到变量str的值,但是你直接在全局去获取str这个变量是获取不到的

image.png

因此我们就可以通过闭包的这一性质来搞点事情

首先创建一个变量 let f = bibao(); 通过控制台console.log(f)可以看到f 就是return的整个函数体,也就是 function(){ return '我是返回的函数' + str }

当执行f()就相当于执行return回来的这个function函数,当我们多次执行f()的时候,可以看到输出的数字在不断的变大。

image.png

当我们再创建一个新的变量 let f2 = bibao(), 然后执行f2(),会看到str的值重置了,又0开始累加

image.png

其实我们可以这样理解,首先闭包是一个匿名函数,现在我们将它赋予了一个变量,那么他就有名字了,那么他每次执行完以后就有地方存了。但是每个变量存的地方又不一样,他们相互不关联,所以他们就是独立的个体了,所以a得值就不同了。就当是执行了不同的函数,只是恰好函数体是一样的罢了

应用场景

比如说我现在的需求是这样的,在网页中有时候会需要遮罩层,调用的时候我就创建一个,但是你不可能每次调用创建吧,所以如果存在就用以前的,如果不存在就创建新的,但同时有可能我永远都不需要这个遮罩层,所以我也有可能一直都不需要创建。这就是一个很典型的单例模式的场景。

function addDiv () {
    let a;
    return function () {
        return a || (a = document.body.appendChild(document.createElement('div')))
    }
}
const add = addDiv()

add()

这样我们就使用到了闭包这一原理

在设计模式中常用到一个场景就是: 在函数中体外需要定义一个变量给函数体内使用,但是又怕污染了全局变量,此时就可以定义一个立即执行的函数,并返回一个闭包给一个变量

以上就是我对闭包的理解啦,谢谢大家的阅读