043|JavaScript闭包

前面我们学习了函数,函数是一个包含可执行代码的对象。实际上,还有另一种包含可执行代码的对象,闭包。

函数的嵌套定义

一个函数的内部可以定义另一个函数,这叫做嵌套定义。嵌套定义的函数和普通函数没有什么区别。
内部函数可以使用外部函数所能引用的变量,而外部函数无法引用内部函数的变量。
我们通过一个例子来理解一下,如:

function sayHi()
{
    var name = "David";
    function getName()  // getName()是一个嵌套定义的函数
    {
        return name // 引用外部函数变量
    }

    console.log("Hello " +getName()) // 此处将会输出"Hello David"
}

sayHi()

上述代码中定义了一个内部嵌套函数getName,getName引用了外部函数sayHi的变量。

闭包

上面代码中,内部的getName函数只在sayHi函数内部使用,所以getName是个普通函数。如果sayHi中将定义的getName函数返回到外部会怎么样?请看下面代码:

function sayHi()
{
    var name = "David";
    function getName()
    {
        return name
    }

    return getName //将getName函数返回到外部
}

var getName = sayHi() // 获取getName函数引用
console.log(getName()) // 调用getName并输出结果

上述代码将嵌套定义的getName函数返回到外部,并调用。我们来看一下运行结果:

043|JavaScript闭包_第1张图片
运行结果

上述代码正常运行了getName函数。

实际上,上述代码中的getName已经不再是个函数,而是一个闭包。

闭包的英文是 Closure,它是JavaScript最重要的几个特性之一。闭包创建于当一个外部函数返回一个内部嵌套定义函数时。所以如果嵌套函数只在内部使用,而未通过retrun 语句抛出,则没能创建建闭包。

闭包的本质

为什么会有闭包呢?

上一节我们学到,当一个函数执行完毕时,其内部变量将无法再被引用到,会被标致为垃圾然后被回收

但在上述代码中,外部函数sayHi返回了一个内部函数getName,内部函数引用了外部函数的name变量,导致当sayHi结束运行时,name变量仍会被引用到

为了保证name不会标记为垃圾,JavaScript对象创建一个闭包来引用name。对于上述程序,闭包本质就是一个下面这样的对象:

closure = {
name:name
func:getName
}

本质上,一个闭包就是一个新建的对象,包含了内部函数执行时需要引用到的所有外部变量,以及内部函数本身。

所以,一句话,闭包是为了嵌套函数能够在任何地方调用而创建的。

好了,这一节就到这里。这一节内容较为抽象,希望你都掌握了。

什么是索引容器?

请继续关注我的课程,我将在后续课程中帮大家依次解答上述问题。

想学计算机技术吗?需要1对1专业级导师指导吗?想要团队陪你一起进步吗?欢迎加我为好友!

我的微信

你可能感兴趣的:(043|JavaScript闭包)