environment简介:
Lua将其所有的全局变量保存在一个常规的table中,这个table称为“环境”,并且为了便于像操作常规table一样,Lua将环境table自身保存在一个全局变量_G中。
在默认情况,Lua在全局环境_G中添加了标准库比如math、函数比如pairs、ipairs等,可以使用以下代码打印当前环境中所有全局变量的名称:
for n in pairs(_G) do
print(n)
end
全局变量声明
在Lua中,全局变量不需要声明就可以直接使用,非常方便,但是这样随便使用全局变量,当出现bug时,也很难去发现,同时也污染了程序中的命名。因为Lua所有的全局变量都保存在一个普通的表中,我们可以使用metatables来改变其他代码访问全局变量的行为,代码如下:
setmetatable(_G,{
__index = function(_,n)
error("attempt to read an undeclared variable "..n,2)
end,
__newindex = function(_,n)
error("attempt to write to undeclared variable "..n,2)
end
})
改变访问全局变量的行为之后,可以使用rawset,来绕过metatable,直接设置table的值:
--file: env.lua
--[[
test ={}
for n in pairs(_G) do
print(n)
end
setmetatable(_G,{
__index = function(_,n)
error("attempt to read an undeclared variable "..n,2)
end,
__newindex = function(_,n)
error("attempt to write to undeclared variable "..n,2)
end
})
data = {}
--]]
local declaredNames = {}
function declare (name, initval)
rawset(_G, name, initval)
declaredNames[name] = true
end
setmetatable(_G, {
__newindex = function (t, n, v)
if not declaredNames[n] then
error("attempt to write to undeclared var. "..n, 2)
else
rawset(t, n, v) -- do the actual set
end
end,
__index = function (_, n)
if not declaredNames[n] then
error("attempt to read undeclared var. "..n, 2)
else
return nil
end
end,
})
declare("data",{"sylvan","yan"})
print(data[1])
非全局的环境
TODO
REF
http://book.luaer.cn/
http://blog.csdn.net/xenyinzen/article/details/3485633