当我拿到_ENV表的时候,会去想这个_ENV表是干什么用的? 首先看如下代码:

 print(_ENV) --0x1d005f0
print(_G) --0x1d005f0

ViewCode

  看了上面的代码,就感觉_ENV表不就是_G表吗?但_ENV表是不是全局的呢?我又打印了_G表的内容:

 for k , v in pairs(_G) do
print(k , v)
end
--[[
package table: 0xad1e50
setmetatable function: 0x419220
pairs function: 0x419380
require function: 0xad3900
loadfile function: 0x419540
print function: 0x418ce0
module function: 0xad3890
rawlen function: 0x418c50
load function: 0x419430
getmetatable function: 0x4195b0
type function: 0x418800
coroutine table: 0xad3970
table table: 0xad3d10
error function: 0x418f40
_VERSION Lua 5.2
debug table: 0xad4bb0
string table: 0xad2700
rawequal function: 0x418ca0
math table: 0xad64d0
tonumber function: 0x418870
bit32 table: 0xad2d60
os table: 0xad3c60
loadstring function: 0x419430
pcall function: 0x4191c0
io table: 0xad4030
select function: 0x418aa0
unpack function: 0x41fb40
collectgarbage function: 0x418fb0
xpcall function: 0x419110
rawset function: 0x418bb0
ipairs function: 0x4193a0
next function: 0x418e20
rawget function: 0x418c00
tostring function: 0x418840
arg table: 0xad76a0
_G table: 0xad15f0
assert function: 0x419680
dofile function: 0x419600
]]

  发现_G表中的Key是没有_ENV表的,就比较疑惑?那_ENV到是什么,是怎么样产生的?关于这两个问题我看了lua闭包

的源码,lua闭包有两种生成方式,其中一种是在lua源码加载时,会生成闭包(ps:关于闭包的整体内容会在之后的另一篇博客讲),

对于该闭包它的第一个Upvalue就是_ENV,具体代码如下:

 LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
const char *chunkname, const char *mode) {
ZIO z;
int status;
lua_lock(L);
if (!chunkname) chunkname = "?";
luaZ_init(L, &z, reader, data);
status = luaD_protectedparser(L, &z, chunkname, mode);
if (status == LUA_OK) { /* no errors? */
LClosure *f = clLvalue(L->top - ); /* get newly created function */
if (f->nupvalues >= ) { /* does it have an upvalue? */
/* get global table from registry */
Table *reg = hvalue(&G(L)->l_registry);
const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
/* set global table as 1st upvalue of 'f' (may be LUA_ENV) */
setobj(L, f->upvals[]->v, gt);
luaC_upvalbarrier(L, f->upvals[]);
}
}
lua_unlock(L);
return status;
}

lua_load中将注册表中的全局表(_G赋值给_ENV)

  所以_ENV默认会指向_G表。至于_G表是如何创建的,各位可以参考这个博客。那_ENV表的作用是什么呢?

  _ENV表的作用:表示当前代码块的环境,每一个代码块的环境都有一张_ENV。关于代码块的解释可以看这里。我们可以看一下下面这段代码就理解了:

 function foorbar(env)
local _ENV = env
return function() print("yes") end
end print(_ENV) local l_test = foorbar({}) print(l_test()) --[[
table: 0x1a395f0
lua: code:3: attempt to call global 'print' (a nil value)
stack traceback:
code:3: in function 'l_test'
code:10: in main chunk
[C]: in ?
]]

  上述可以看出,我们的所有内部函数都定义与一张_ENV表中,比如在print时实际上是_ENV.print(语法糖省略了),所以在代码块foorbar中_ENV被赋值为{},所以print就访问不到了。

所以_ENV表的作用实际上是充当环境,所以在5.2之后就没有全局变量这样一个说法(_ENV = _G还是有全局变量的)。这种做法类似于5.1的setfenv。关于如何实现setfenv在云风的博客有提及。

对lua中_ENV表的理解(lua5.2版本以后)的更多相关文章

  1. 【转载】Lua中实现类的原理

    原文地址 http://wuzhiwei.net/lua_make_class/ 不错,将metatable讲的很透彻,我终于懂了. --------------------------------- ...

  2. Lua中table的实现-《Lua设计与实现》

    本文来自<Lua设计与实现>的阅读笔记,推荐Lua学习者可以购买一本,深入浅出讲解lua的设计和实现原理,很赞,哈哈   Lua中对于表的设计,是基于数组和散列表,和其他语言不同,对于数组 ...

  3. lua中是 ffi 解析 【是如何处理数据包的/pkt是如何传进去的】 fsfsfs

    lua中的ffi是如何解析的呢? 拿bcc中对proto的解析说起: metatype是有大学问的: ffi.metatype(ffi.typeof('struct ip_t'), { __index ...

  4. Cocos2d-x 脚本语言Lua基本数据结构-表(table)

    Cocos2d-x 脚本语言Lua基本数据结构-表(table) table是Lua中唯一的数据结构.其它语言所提供的数据结构,如:arrays.records.lists.queues.sets等. ...

  5. Lua中的weak表——weak table

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  6. Lua中的weak表——weak table(转)

    弱表(weak table)是一个很有意思的东西,像C++/Java等语言是没有的.弱表的定义是:A weak table is a table whose elements are weak ref ...

  7. lua中常量的实现及表的深拷贝实现

    废话:好久没在这里写博客了...主要原因是我买了个域名hanxi.info并在github上搭建了个人博客... lua中默认是没有c中的const常量的,在csdn上找到了一个使用setmetata ...

  8. 理解lua中 . : self

    前言 在LUA中,经常可以看到:. self,如果你学习过Java或C#语言,可以这样理解 .对于c#和java的静态方法 :相当于是实例方法 今天在CSDN上看到一篇博客写的很清楚,转载过来 原文出 ...

  9. 两个函数彻底理解Lua中的闭包

    本文通过两个函数彻底搞懂Lua中的闭包,相信看完这两个函数,应该能理解什么是Lua闭包.废话不多说,上 code: --[[************************************** ...

随机推荐

  1. RAD Studio 2010 环境设置(转)

    源:RAD Studio 2010 环境设置 最近在使用RAD Studio 2010做一些开发和实验,但在安装了自定义的控件及第三方下载的控件后,在我的工程里经常会提示找不到DCU,为了以后忘记这一 ...

  2. typedef和block

    为block类型对象取别名 1.没有使用typedef的情况 int (^block_add)(int, int) = ^(int value1, int value2) { return value ...

  3. Lua学习系列(四)

    lua 资源:http://www.dcc.ufrj.br/~fabiom/lua/ 第一个Lua程序 http://www.dcc.ufrj.br/~fabiom/lua/ 原文:https://w ...

  4. Centos rsync文件同步配置

    一.服务器端配置: # yum -y install xinetd   CentOS默认已经安装了rsync 服务.. 输入 rsync 命令可查看是否安装.   # vi /etc/xinetd.d ...

  5. HDU 5624 KK's Reconstruction

    这题目测是数据水了.我这种暴力写法显然是可以卡超时的. 假设有2000个点,15000条边,前面10000条不能构成树,后面5000条可以,这种数据显然可以卡超时. #include <stdi ...

  6. Ubuntu下搭建C++开发环境

    Ubuntu使用eclipse搭建c/c++编译环境----CDT插件 Ubuntu(Linux)使用Eclipse搭建C/C++编译环境          这两天,给自己电脑弄了双系统,除了原来的W ...

  7. Python字符串的encode与decode研究心得——解决乱码问题

    转~Python字符串的encode与decode研究心得——解决乱码问题 为什么Python使用过程中会出现各式各样的乱码问题,明明是中文字符却显示成“/xe4/xb8/xad/xe6/x96/x8 ...

  8. 《javascript语言精粹》——第6章数组

    [1].数组字面量 var empty=[]; var num=[ 'zero','one','two','three','four','five','six','seven','eight','ni ...

  9. Linux怎样访问Windows共享文件和文件夹

    常常使用Windows的人可能会发现,Windows计算机之前共享资料非常方便,但是有时候想玩玩Linux的时候,如Fedora.Ubuntu.CentOS等,该怎样才能访问Windows计算机上的文 ...

  10. IOS开发中长按的手势事件编程

    长按手势事件: 长按按钮1S后改变按钮颜色: // 长按事件 #import "ViewController.h" @interface ViewController (){ UI ...