前面我们学习了函数,函数是一个包含可执行代码的对象。实际上,还有另一种包含可执行代码的对象,闭包。
函数的嵌套定义
一个函数的内部可以定义另一个函数,这叫做嵌套定义。嵌套定义的函数和普通函数没有什么区别。
内部函数可以使用外部函数所能引用的变量,而外部函数无法引用内部函数的变量。
我们通过一个例子来理解一下,如:
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函数返回到外部,并调用。我们来看一下运行结果:
运行结果上述代码正常运行了getName函数。
实际上,上述代码中的getName已经不再是个函数,而是一个闭包。
闭包的英文是 Closure,它是JavaScript最重要的几个特性之一。闭包创建于当一个外部函数返回一个内部嵌套定义函数时。所以如果嵌套函数只在内部使用,而未通过retrun 语句抛出,则没能创建建闭包。
闭包的本质
为什么会有闭包呢?
上一节我们学到,当一个函数执行完毕时,其内部变量将无法再被引用到,会被标致为垃圾然后被回收。
但在上述代码中,外部函数sayHi返回了一个内部函数getName,内部函数引用了外部函数的name变量,导致当sayHi结束运行时,name变量仍会被引用到。
为了保证name不会标记为垃圾,JavaScript对象创建一个闭包来引用name。对于上述程序,闭包本质就是一个下面这样的对象:
closure = {
name:name
func:getName
}
本质上,一个闭包就是一个新建的对象,包含了内部函数执行时需要引用到的所有外部变量,以及内部函数本身。
所以,一句话,闭包是为了嵌套函数能够在任何地方调用而创建的。
好了,这一节就到这里。这一节内容较为抽象,希望你都掌握了。
什么是索引容器?
请继续关注我的课程,我将在后续课程中帮大家依次解答上述问题。
想学计算机技术吗?需要1对1专业级导师指导吗?想要团队陪你一起进步吗?欢迎加我为好友!
我的微信
网友评论