lua中的闭包概念的学习笔记

1、闭包的由来:

  个人理解,lua中之所以出现闭包的概念,完全是因为lua中允许函数的嵌套定义,并且在内嵌函数中使用了外包函数中定义的局部变量,例如c、c#就不允许函数的嵌套定义(但是允许函数的嵌套调用)

以下是函数嵌套定义的一个例子:

1 function fun1(n)
2     local function fun2()
3         print(n)
4     end
5 
6     return fun2
7 end

fun1叫做fun2的外包函数,fun2叫做fun1的内嵌函数,并且这中内嵌与外包关系是允许传递的。什么意思呢?就是fun1的外包函数也是fun2的外包函数,fun2的内嵌函数也是fun1的内嵌函数。

我们都知道,函数中定义的局部变量的生命周期就是在函数运行完后就结束了。假如现在有如下逻辑:

1 fun3 = fun1(2048)
2 fun3()

执行结果如下:

从执行结果上看,2048的生命周期好像不是在fun1执行完就结束的,看着像是在fun2执行完才结束的。事实是这样的吗?

 当fun3被调用时,其函数体访问了外部的局部变量n。当调用fun2函数时,创建fun2的fun1函数已经返回了,即执行结束,那么外部局部变量的生命周期也就结束了,这个时候在fun2中继续如何访问局部变量 n 呢?

闭包就是为了解决这个问题出现的。

其实不同的语言,对该问题有不同的处理方式,例如c、c#直接就不允许函数的嵌套定义,从根源避免问题的产生;python则是通过限定作用域来解决该问题。

2、编译时: lua编译一个函数时,会为它生成一个原型(prototype) --- 包括 函数体对应的虚拟机指令、函数执行用到的常量、一些调试信息。

   运行时: 每当lua执行一个形如function...end 这样的表达式时,它就会创建一个新的数据对象,其中包含了相应函数原型的引用、环境(environment,用来查找全局变量的表)的引用以及一个由所有upvalue引用组成的数组,而这个数据对象就称为闭包。

   即函数是编译期概念,是静态的,而闭包是运行期概念,是动态的。

3、词法定界:当一个函数内嵌套另一个函数的时候,内函数可以访问外部函数的局部变量,这种特征叫做词法定界。

   闭包的产生:调用了某种类型的外包函数产生的一个实例函数(类似上面的代码示例),这个外包函数满足,它的内嵌函数访问了在它中定义的局部变量。

   闭包组成:外部函数+外部函数创建的局部变量+内部函数(闭包函数)

参考:https://blog.csdn.net/maximuszhou/article/details/44280109

  https://www.cnblogs.com/zzy-frisrtblog/p/5864209.html

  http://blog.chinaunix.net/uid-52437-id-2108789.html

猜你喜欢

转载自www.cnblogs.com/luguoshuai/p/10049288.html