lua没有全局变量,为什么这样设计呢?
以这个文件为例说明 test.lua
-------------------------------------
a = 100;
local m = 4;
function foo()
local i = 5;
print(a, m, i);
function bar()
print(a, m, i);
end
end
首先整个文件是个函数,它本身有个默认的变量G(upval类型)。任何函数里面都可以再定义函数,变量会往最外层找它的出处,如果没有,则变成G['varname']。
所以以上的变量会是这样的:
对文件这个函数,有3个变量a, m, foo,函数名本身也是。
a => G['a'];
m => local;
foo => G['foo'];
对foo这个函数,有4个变量i, print, a, m, bar。
i => local
print => G['print'];
m => upval
bar => G['bar']
对bar这个函数,有4个变量print, a, m, i。
print => G['print'];
a => G['a'];
m => upval;
i => upval;
我们解释下什么是local和upval。
local是已经声明为local的局部变量,lua变量跟js有点类似,除非显示声明为局部变量,否则是其它类型。local这样很好理解。
upval是在本函数里没有声明,但是在外层有声明的变量。简单讲就是在外层是local,或已经是upval的,属于本层函数的变量,如foo里的m,bar里的i。
G本身已经是个upval,它的值是一个lua里面的hash table。
现在我们知道lua有两种类型了:local和upval。那如果加上数组后会怎么样呢? 比如上面的foo函数,m是upval,那么m['k']则是tabup。i是local,那么i['k']则是table。因此lua总共就4种类型 local, upval, table, tabup。因此任何看似全局变量的,其实是tabup,也就是G['var']。lua就是这样通过抽象把全局变量给抹掉了。
相关推荐
在Lua中,所有未在局部作用域中定义的变量都是全局变量,但全局变量实质上是全局表的一个键。环境变量则是每个函数都有自己的环境,这个环境是一个指向表的引用,通常用于实现模块化的封装。 6. **C API**: 提供...
4. **环境与全局变量**:Lua中的所有全局变量实质上都是全局环境表的一个字段,理解这一点对于避免命名冲突和管理作用域至关重要。 5. **垃圾回收**:Lua自动进行内存管理,使用引用计数加可达性分析的垃圾回收机制...
理解如何管理全局变量和创建局部作用域是编写可维护代码的关键。 4. **垃圾回收**:Lua自动进行内存管理,使用引用计数和可达性分析的混合策略来实现垃圾回收,开发者需要了解这一机制以避免内存泄漏。 5. **C接口...
2.5 可见性规则:定义了变量和函数的作用域。 3. 应用程序接口(API): 3.1 栈:Lua使用栈来管理函数调用和返回值。 3.2 栈的大小:API允许操作栈的大小。 3.3 有效索引与合法索引:解释如何在Lua中正确地引用...
7. **环境变量和全局变量**:Lua 中的全局变量实质上是全局环境表的一个键值对,环境变量可以被用来模拟作用域。 8. **协程(Coroutines)**:Lua 的协程是一种轻量级线程,可以实现并发执行,但不涉及系统级别的...
闭包是Lua中的重要概念,它允许函数访问并操作其外部作用域的变量,即使该函数已经返回。 4. **元表(Metatables)**:Lua通过元表实现动态类型和运行时反射。元表可以改变基本操作的行为,如索引、相等性检查等,...
- **闭包**:函数可以访问并修改其创建时的环境,实现函数作用域的持久化。 - **协程(Coroutine)**:轻量级的并发机制,可以在单线程中实现类似多线程的效果。 在学习和使用LuaForWindows时,你需要掌握以下几点...
- **作用域**:确保在回调函数中引用的变量在其作用域内是可见的。如果需要访问全局变量,记得使用`global`关键字。 - **回调地狱**:避免过多嵌套的回调,这可能导致代码难以理解和维护。考虑使用Promise或者...
这里的“引用环境”指的是函数能够访问的那些变量,这些变量通常是在包含它的函数(即外部函数)的作用域中定义的。闭包的这种特性使得它能够在函数执行完毕后仍然保持对外部作用域中变量的引用。 #### 闭包的实例 ...
编写模块的基本方法包括定义模块作用域内的常量和函数,并在最后返回一个table,该table包含了模块的所有公有接口。通常,我们会把模块名作为require函数的参数,这样在重命名模块的时候,只需要修改文件名而不需要...
5. **闭包**:JavaScript中的闭包允许函数访问并操作其外部作用域的变量,即使在外部函数执行完毕后。 6. **原型和继承**:JavaScript对象基于原型链进行继承,可以通过__proto__属性或Object.create方法实现。 7....