局部变量与全局变量的比较
- 实现:局部变量通过栈上的寄存器数组进行索引,具有硬编码的整数索引(至少在标准实现中如此 -- LuaImplementations)。全局变量通过表格(或 userdata)进行索引,通常使用变量名的字符串作为键,存储为常量或变量。
- 注意:在 5.2.0work3 中,全局变量的概念仍然存在于语言中,但已从虚拟机中移除(没有特殊的 GETGLOBAL/SETGLOBAL 操作码)。从虚拟机的角度来看,全局变量与局部变量(实际上是词法上的 upvalue)表格的获取/设置没有区别。
- 注意:晋升为 upvalue 的局部变量在虚拟机中与常规局部变量的处理方式略有不同。Upvalue 通过特殊虚拟机操作码访问。
- 语法:如果设置了环境表格,则可以在 Lua 代码中访问全局变量,无论是否明确指定其所属的环境表格:
foo、_G.foo 或 getfenv().foo(在 5.2.0work3 中是 _ENV.foo)。这允许不同的环境使用风格,例如在 ModuleDefinition 中。
- 作用域:局部变量的作用域限制在词法块内。全局变量的作用域在运行时被分配了给定环境表格的任意数量的函数中。在 5.2.0work3 中,全局变量的作用域在编译时声明但运行时分配了给定环境表格的任意数量的词法块中。
- 声明:局部变量必须使用
local 语句显式声明才能使用。赋值默认是全局的,而不是 LocalByDefault。全局变量可以即时访问,即使变量名是在运行时设置的(例如,“foo=io.stdin:read'*l'; return _G[foo]”)。局部变量的列表是静态定义的。全局变量的列表可能在运行时确定,甚至可以在程序执行期间更改。
- 标准库访问:标准库通常通过全局变量暴露给一个代码块。然而,另一种选择是将 _G 或其元素显式地作为局部参数传递,“
local _G, math, math_sqrt = ...”,但这可能非常繁琐。
- 优先级:局部变量覆盖全局变量。即使全局变量具有更具体的作用域,这一点仍然成立,因此在 5.2.0work3 中,“
local x = 1; do local _ENV = {x=2}; return x end”返回 1。
- 作用域传递:可以通过传递环境表格将一组完整的全局变量或对全局变量的引用传递到不同的作用域。全局作用域在某种程度上是 Lua 中一种“一等阀门”。局部变量无法像这样传递,除非通过创建显式引用了这些局部变量的闭包。一个例外是 debug.getlocal/setlocal,如 StringInterpolation 中使用,但这是一种 hack。
- 字节码内省:全局变量在字节码中更可见。全局获取/设置变为带有给定变量名的 GETGLOBAL/SETGLOBAL 操作码。在 5.2.0work3 中,它们变为 GETTABUP/SETTABUP 操作码 [1]。可以列出由编译后的代码块读取或写入的所有全局变量,例如 DetectingUndefinedVariables 所使用的。
- 数量限制:每个函数允许的局部变量数量有限(MAXLOCALS,通常为 200)。
RecentChanges · preferences
编辑 · 历史
最后编辑于 2010 年 7 月 10 日下午 4:35 GMT (差异)