对lua中_ENV表的理解(lua5.2版本以后)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了对lua中_ENV表的理解(lua5.2版本以后),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2985字,纯文字阅读大概需要5分钟。
内容图文
当我拿到_ENV表的时候,会去想这个_ENV表是干什么用的? 首先看如下代码:
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944674.jpg)
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944699.jpg)
1 print(_ENV) --0x1d005f02print(_G) --0x1d005f0
看了上面的代码,就感觉_ENV表不就是_G表吗?但_ENV表是不是全局的呢?我又打印了_G表的内容:
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944674.jpg)
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944699.jpg)
1 for k , v inpairs(_G) do 2print(k , v) 3end 4--[[ 5package table: 0xad1e50 6setmetatable function: 0x419220 7pairs function: 0x419380 8require function: 0xad3900 9loadfile function: 0x419540 10print function: 0x418ce0 11module function: 0xad3890 12rawlen function: 0x418c50 13load function: 0x419430 14getmetatable function: 0x4195b0 15type function: 0x418800 16coroutine table: 0xad3970 17table table: 0xad3d10 18error function: 0x418f40 19_VERSION Lua 5.2 20debug table: 0xad4bb0 21string table: 0xad2700 22rawequal function: 0x418ca0 23math table: 0xad64d0 24tonumber function: 0x418870 25bit32 table: 0xad2d60 26os table: 0xad3c60 27loadstring function: 0x419430 28pcall function: 0x4191c0 29io table: 0xad4030 30select function: 0x418aa0 31unpack function: 0x41fb40 32collectgarbage function: 0x418fb0 33xpcall function: 0x419110 34rawset function: 0x418bb0 35ipairs function: 0x4193a0 36next function: 0x418e20 37rawget function: 0x418c00 38tostring function: 0x418840 39arg table: 0xad76a0 40_G table: 0xad15f0 41assert function: 0x419680 42dofile function: 0x419600 43]]
发现_G表中的Key是没有_ENV表的,就比较疑惑?那_ENV到是什么,是怎么样产生的?关于这两个问题我看了lua闭包
的源码,lua闭包有两种生成方式,其中一种是在lua源码加载时,会生成闭包(ps:关于闭包的整体内容会在之后的另一篇博客讲),
对于该闭包它的第一个Upvalue就是_ENV,具体代码如下:
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944674.jpg)
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944699.jpg)
1 LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, 2 const char *chunkname, const char *mode) { 3 ZIO z; 4 int status; 5 lua_lock(L); 6if (!chunkname) chunkname = "?"; 7 luaZ_init(L, &z, reader, data); 8 status = luaD_protectedparser(L, &z, chunkname, mode); 9if (status == LUA_OK) { /* no errors? */ 10 LClosure *f = clLvalue(L->top - 1); /* get newly created function */ 11if (f->nupvalues >= 1) { /* does it have an upvalue? */ 12 /* get global table from registry */ 13 Table *reg = hvalue(&G(L)->l_registry); 14 const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); 15 /* set global table as 1st upvalue of ‘f‘ (may be LUA_ENV) */ 16 setobj(L, f->upvals[0]->v, gt); 17 luaC_upvalbarrier(L, f->upvals[0]); 18 } 19 } 20 lua_unlock(L); 21return status; 22 }
所以_ENV默认会指向_G表。至于_G表是如何创建的,各位可以参考这个博客。那_ENV表的作用是什么呢?
_ENV表的作用:表示当前代码块的环境,每一个代码块的环境都有一张_ENV。关于代码块的解释可以看这里。我们可以看一下下面这段代码就理解了:
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944674.jpg)
![技术分享](/upload/getfiles/default/2022/11/8/20221108051944699.jpg)
1 function foorbar(env) 2 local _ENV = env 3returnfunction() print("yes") end 4end 5 6print(_ENV) 7 8local l_test = foorbar({}) 910print(l_test()) 1112--[[13table: 0x1a395f0 14lua: code:3: attempt to call global ‘print‘ (a nil value) 15stack traceback: 16 code:3: in function ‘l_test‘ 17 code:10: in main chunk 18 [C]: in ? 19]]
上述可以看出,我们的所有内部函数都定义与一张_ENV表中,比如在print时实际上是_ENV.print(语法糖省略了),所以在代码块foorbar中_ENV被赋值为{},所以print就访问不到了。
所以_ENV表的作用实际上是充当环境,所以在5.2之后就没有全局变量这样一个说法(_ENV = _G还是有全局变量的)。这种做法类似于5.1的setfenv。关于如何实现setfenv在云风的博客有提及。
原文:http://www.cnblogs.com/yuyaonorthroad/p/6337506.html
内容总结
以上是互联网集市为您收集整理的对lua中_ENV表的理解(lua5.2版本以后)全部内容,希望文章能够帮你解决对lua中_ENV表的理解(lua5.2版本以后)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。