问题引入
在一些编程语言中,函数嵌套使用时,存在这样一种情况:外层函数的生命周期已经结束,而内层函数要访问外层函数中的变量。如果没有函数闭包的支持,这将会存在问题。
以Scala语言为例,试考虑下面这种情况:
object Closure {
def main(args: Array[String]): Unit = {
def fun_outer(x: Int): Int => Int = {
def fun_inner(y: Int): Int = x + y
fun_inner
}
println(fun_outer(1)(2))
}
}
分析:两个函数嵌套使用,外部函数将内部函数作为返回值,内部函数的函数体内引用了外部函数的参数x
- 执行到
fun_outer(1)时,1赋值给外部形参x上fun_outer将fun_inner的引用(内存地址)返回fun_outer执行结束,x的作用域结束,销毁- 回到主程序后,继续调用
fun_outer(1)(2),可以理解为调用fun_inner(2)- 此时程序执行
x + y时,y的值由参数2提供,但是x的值已经销毁,问题由此出现
那么,如何解决这个问题呢?那就需要闭包的支持了。
什么是闭包
MDN给出的闭包的定义:
闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。
如果用一个公式来概括,闭包 = 函数 + 引用环境
结合前面的例子分析:fun_inner由于引用了fun_outer中的局部变量x,所以x和fun_inner共同组成了一个闭包。闭包存储于堆中,即使fun_outer的栈指针已经释放,但闭包的环境仍然保留下来,从而解决了作用域问题。
总结
- 闭包是函数及其引用环境的组合。
- 闭包突破了函数作用域的限制,解决了函数内部访问函数外部作用域的情况。
- 闭包存储于堆中,若滥用且不及时释放空间,可能导致内存溢出。在JVM中,闭包的释放依赖于GC垃圾回收机制。
希望这篇文章让你有所收获,如有错误也欢迎指正!
闭包是一个函数及其引用环境的组合,允许内部函数访问并保持对外部作用域的引用。在Scala示例中,当fun_outer返回fun_inner时,它们共同形成闭包,保存了x的值,即使fun_outer执行完毕。闭包存储在堆中,如果管理不当可能导致内存溢出,依赖GC进行回收。
327





