闭包函数到底是什么?有什么用?
转载请注明出处即可,无需经过我本人同意。
以下内容为网上的内容加上本人的理解,如有侵权,请通知本人删除文章。
闭包函数是什么:
首先看如下代码,你是否了解其真正的意义:
function test()local i=0return function()i=i+1return iend
enddoTest=test()
print(doTest()) --输出1
print(doTest()) --输出2
你可能有这样的疑问:
1. 调用test()返回的函数doTest()时,变量 i 的定义在哪?
2. test()中的i不是局部变量吗?为什么返回的函数还能调用。
如果你有这样的疑问,请接着往下看。
首先,了解几个概念:
词法定界:当一个函数内嵌套另一个函数的时候,内函数可以访问外部函数的局部变量,这种特征叫做词法定界。而这些变量就被称为该内嵌函数的upvalue,upvalue实际指的是变量而不是值,这些变量可以在内部函数之间共享。
闭包:通过调用含有一个内部函数加上该外部函数持有的外部局部变量(upvalue)的外部函数(外部函数就是工厂)产生的一个实例函数。
闭包组成:外部函数+外部函数创建的upvalue+内部函数(闭包函数)
如上面的函数test(),
test()就是外部函数,
外部函数的局部变量local i=0就是upvalue(也叫做非局部变量,之所以叫做非局部变量,是因为此变量的作用域既不是局部变量的作用域,也不是全局变量的作用域。),
返回的函数就是内部函数。
现在再回头看看原来的函数,我们知道了这种形式的函数叫做闭包函数。而test()中的局部变量i是内嵌函数的upvalue(非局部变量),且在内部函数中共享。
重复调用内部函数时,每一个调用都会记住上一次调用后的值,就是说第一次调用doTest()之后,i 的值已经是1了。
下面再看个例子
function test()local i=0return function()i=i+1return iend
enddoTest=test()
doAgain=test()
print(doTest()) --输出1
print(doTest()) --输出2print(doAgain()) --输出1
print(doAgain()) --输出2
可以看到,此时执行doAgain()时 i 值并没有在原来的基础上增加。
原因是:
doTest,doAgain是建立在同一个函数,同一个局部变量的不同实例上面的两个不同的闭包。
调用一次test()就会产生一个新的闭包, 而闭包中的upvalue各自独立。所以不难解释为什么doAgain()的i 值为什么没有在原来的基础上增加了。
闭包函数有什么用:
在for in 的循环中需要使用到迭代器,而迭代器需要保留上一次调用的状态和下一次成功调用的状态,刚好可以使用闭包的机制来实现。
创建迭代器:
function list_iter(t) --外包函数叫做工厂函数。local i=0local n=table.getn(t)return function()i=i+1if i<=n then return t[i] endendend
--[[这里的list_iter是一个工厂,每次调用都会产生一个新的闭包。该闭包内部包括了upvalue(t,i,n)。
因此每调用一次该函数产生的闭包,那么该闭包就会根据记录上一次的状态,以及返回list的下一个。]]
在while中使用:
--while中使用:
t={10,20,90}
iter=list_iter(t) --调用迭代器产生一个闭包
while true do
--当闭包函数的i值已经等于n的值时,依然会执行闭包函数,此时返回的就是nil.
--如果没有下面的判断,while就会一直循环,并进入死循环。local element=iter()if element==nil then break endprint(element)
end
在泛型for使用
--泛型for使用:
t={10,0,29}
--这里的list_iter()工厂函数只会被调用一次产生一个闭包函数,
--后面的每一次迭代都是用该闭包函数,而不是工厂函数。
for element in list_iter(t) doprint(element)
end如果想要同时返回k,v值,需要修改工厂函数,如下所示:function list_iter(tb)local i = 0return function ()i = i + 1--如果没有下面这个判断,就会一直执行。--详情可以看我的另一篇博客,《Lua内容关于for循环的总结》if tb[i] == nil then return nilend return i,tb[i]end
end
闭包函数到底是什么?有什么用?相关推荐
- 闭包函数 装饰器 迭代器
闭包函数 一.什么是闭包 闭包:闭是封闭(函数内部函数),包是包含(该内部函数对外部作用域而非全局作用域的变量的引用).闭包指的是:函数内部函数对外部作用域而非全局作用域的引用.简单的说闭包函数就是把 ...
- Python基础day4 函数对象、生成器 、装饰器、迭代器、闭包函数
一.函数对象 正确理解 Python函数,能够帮助我们更好地理解 Python 装饰器.匿名函数(lambda).函数式编程等高阶技术. 函数(Function)作为程序语言中不可或缺的一部分,太稀松 ...
- python 函数进阶-闭包函数
闭包函数 什么是闭包函数 如果内函数使用了外函数的局部变量,并且外函数把内函数返回出来的过程叫做闭包,里面的内函数是闭包函数. # 外函数 outer def outer():# 外函数变量 numv ...
- JavaScript闭包函数箭头函数调用与执行
一.标准的闭包函数 //一.标准的闭包函数 function A() {var i=0;++i;console.log('i : ' + i);return function b() {return ...
- php的匿名函数和闭包函数
php的匿名函数和闭包函数 tags: 匿名函数 闭包函数 php闭包函数 php匿名函数 function use 引言:匿名函数和闭包函数都不是特别高深的知识,但是很多刚入门的朋友却总是很困惑,因 ...
- 写的函数符号表里没有_你有没有想过,C语言 main 函数到底为啥这么写?
但凡是学过C语言的人,都知道要先写main函数,然而很多时候我们看到的main函数却各有差异,这究竟是为啥?哪种是对的呢?今天我们就来聊聊main函数. 那么main函数一共有多少个版本呢? 1.ma ...
- php的闭包函数bingto_PHP 闭包那点事儿
匿名函数 匿名函数,也叫闭包函数,说白了就是"没有名字的函数",和一般函数结构一样,只是少了函数名以及最后需要加上分号;. 注:理论上讲闭包和匿名函数是不同的概念,不过PHP将其视 ...
- python命名空间和闭包_Python函数基础实例详解【函数嵌套,命名空间,函数对象,闭包函数等】...
本文实例讲述了Python函数基础用法.分享给大家供大家参考,具体如下: 一.什么是命名关键字参数? 格式: 在*后面参数都是命名关键字参数. 特点: 1.约束函数的调用者必须按照Kye=value的 ...
- char怎么比较_C语言的 main 函数到底怎么写才是对的?
相信各位对C语言中的 main 函数大家都再熟悉不过了,这是你学习C语言首先就要学习的东西,但是我看过很多人写的代码包括我的一些读者在main函数的写法方面版本很多,今天就跟大家聊一聊main函数到底 ...
最新文章
- deepin中mysql数据库的连接_Python爬虫进阶教程(八):MySQL 数据库连接
- dhcp配置(个人)
- leetcode -eleven:Container With Most Water
- Linux下KVM虚拟机基本管理及常用命令(转)
- Linux CA证书与https讲解
- 和feign的区别_Feign的传参研究
- IDEA-Maven的Dependencies中出现红色波浪线
- c语言人机大战五子棋,五子棋人机大战将打响 祁观将与AI弈心五番棋对决
- 基于RFM模型的Kmeans聚类算法实现
- c语言中isupper用法,C语言中的isupper()函数
- 国产手机的18年历史
- JAVA实现时间换算
- 一行代码视频下载,so easy!
- Heapsort 代码 学习笔记 阳春三月版
- 修改php fpm监听端口,怎样修正php fpm监听端口_后端开发
- Codeforces - Serval and Parenthesis Sequence
- 阿里云服务器地域暂时无法办理经营性ICP许可证什么意思?
- centos 7.5 内核升级
- fractions -- 分数
- QT简单实验——计算器
热门文章
- php war包,War包 - java,ruby,net,css,php,C++,Python,
- Java程序员已经饱和了?这是个老话题了
- 自己制做立体影像! 揭秘你不知道的3D
- Prometheus+Clickhouse实现业务告警
- 顺丰2020年财报幕后:不可轻视的科技力量和新增长曲线
- ASP.NET使用文件流的方式下载文件
- 刘强东给高管兄弟降薪:2千多位总监工资打8折!同时拿出100亿保障基础员工住房
- Java使用zip4j进行文件压缩
- java计算机毕业设计疫情展示平台源码+数据库+系统+lw文档+部署
- base64文件流转换成pdf格式下载/打印,兼容IE浏览器