JavaScript之闭包

这是我参与更文挑战的第11天,活动详情查看:更文挑战

首先我们来看一个例子:

function foo() {
        var myName = "啊巴啊巴"
        let test1 = 1
        const test2 = 2
        var innerBar = {
            getName: function() {
                console.log(test1)
                return myName
            },
            setName: function(newName) {
                myName = newName
            }
        }
        return innerBar
    }
    var bar = foo()
    bar.setName("伊卡巴卡")
    bar.getName()
    console.log(bar.getName())
复制代码

构成闭包的是myNametest1

此时有全局执行上下文和foo函数执行上下文,而执行上下文当中又分为变量环境和词法环境

image.png

图片来自于极客时间专栏课程

在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。比如外部函数是 foo,那么这些变量的集合就称为 foo 函数的闭包。

所以实际上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

那么我们再看看下面这段代码:

  var bar = { // 注意:此时的bar不是函数,而是变量
        myName: "阿巴阿巴", // 因此该myName只是对象的一个属性
        printName: function() { // 这里的printName是一个全局声明的函数
            console.log(myName)
        }
    }

    function foo() {
        let myName = "伊卡巴卡"
        return bar.printName // 调用的是bar变量,所以跟上一行的myName变量无关
    }
    let myName = "巴巴巴巴"
    let _printName = foo()
    _printName() // 巴巴巴巴
    bar.printName() //  巴巴巴巴

复制代码

上面的这段代码不构成闭包。因为_printName()调用的foo()函数 return 的是bar变量,也就是跟foo函数里的myName无关。 然后因为 bar不是函数而是变量,所以跟bar里面的myName属性无关。最终寻找全局执行上下文中的词法环境中的myName也就是“巴巴巴巴”。

所以总结来说,闭包其实就是能够读取其他函数的内部变量的函数。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享