JavaScript 闭包 Closure

前置知识:需要了解作用域

闭包的概念:

MDN:

闭包是由捆绑起来(封闭的)的函数和函数周围状态(词法环境)的引用组合而成。

提取这句话中两个关键词并用公式表示:

闭包 = 捆绑起来(封闭的)的函数 + 函数周围状态(词法环境)

简单点来说,根据黑马pink老师的话,就是

闭包 = 内层函数 + 外层函数的变量

再用图像来理解,或许能清晰一点

接下来用代码表示

function outer() {
    const fruit = 'apple'
    function inner() {
        console.log(fruit)
    }
    inner()
}
outer()

当我们调用outer方法时,代码从上往下执行,先声明并赋值了一个变量fruit,接下来声明了内部方法inner,然后开始调用内部方法inner,从而在控制台打印出'apple'。

当然,这时候,不禁就要问了,如果我们只是为了打印出‘apple’,这样做岂不是多此一举?

没错,确实是多此一举,这样写只是为了方便理解闭包的概念,而闭包的主要作用并不在此。

闭包的应用:

先来看一个场景

页面中有一个按钮,每点击一次,就让控制台打印出点击的次数,代码如下所示:

    <button>按钮</button>
    <script>
        let num = 0
        function add() {
            num++
            console.log(`按钮被点击了${num}次`)
        }
        document.querySelector('button').addEventListener('click', add)
    </script>

此时变量的num声明于全局作用域下,是一个全局变量,很容易被修改,我们希望这个num变量,只用来记录这个button,那么怎样才能让他更安全一点呢?我们就可以用到闭包,从而实现数据私有化!

在实现闭包前,我们先回想下闭包的公式,其中两个关键元素,内层函数和外层函数的变量,那么在这个方法中,谁是内层函数,谁是外层函数的变量呢?

内层函数就是我们真正要执行的逻辑

外层函数的变量就是执行这块逻辑要用到的变量

外层函数的作用就是把他们包起来

因此,内层函数就是add这个函数,而外层函数变量则是num这个变量

接下来,我们只差一个外层函数把他们包起来了,同时不要忘记把内层函数调用一次

然而,当我们打开控制台后, 事情并没有朝着我们希望的方向进行

无论点击了多少次,num仍然为1!

这是因为我们每次点击按钮时,outer被调用,然后重新定义num变量并将其初始化为0,接着在内部的add方法使得num加一。

那么怎样才能保留num的状态?

为了解决这个问题,我们需要使用return关键字,将内部函数add返回出去,再用一个新变量接受它,最后,每次点击时调用这个新变量。

这样说有点生硬,为了方便解释,我添加了一句log在初始化num后面

代码如下:

function outer() {
    let num = 0
    console.log('num', num)
   
    return function() {
        num++
        console.log(`按钮被点击了${num}次`)
    }
}

const returnOuter = outer() // 方法加上括号,表示调用

document.querySelector('button').addEventListener('click', returnOuter)

整个运行的流程为

当我们打开页面时,由于我们一开始就调用了outer(),所以控制台就会打印出‘num 0’,这也说明页面已经初始化了这个num变量,同时也返回了函数给returnOuter。

类似于: 

接下来每点击一次,都会调用returnOuter这个方法,里面的num也不会被重置了

总结一下:

闭包是内层函数和外层函数变量的结合,可以实现数据的私有化(封闭数据,提供操作),同时外部也可以访问其内部的变量(正如 const returnOuter = outer())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值