一、前言
Lua 是动态语言,无法区分常量和变量。
二、_G
Lua 将全局变量保存在一个全局环境的表中,而这个表就是 _G ,因为 _G 是一个表所以可以像其他表一样操作。
值得注意的是,_G._G
指向自身 _G
,即 _G._G == _G
,这样才能在代码段中正常的使用 _G
变量(下面的章节会分享为什么)
打印 _G
和 _G._G
便可印证这一点
print(_G, _G._G) --> table: 0x600001ff0200 table: 0x600001ff0200
我们设置的所有的全局变量,如果没有其他的特殊处理(后面小节会分享有什么特殊处理),都会最终存储在全局变量 _G 中。
print("_G.age", _G.age) --> _G.age nil
age = 100
print("age", age) --> age 100
print("_G.age", _G.age) --> _G.age 100
三、_ENV
1、_ENV 是什么
在 Lua 中,会为每个代码段增加一个预定义上值,即 _ENV 。他是一个外部局部变量,会将代码段中使用的 “全局变量” 存在这个 _ENV 中。
Lua 编译器会将以下代码段进行转换,全局变量都会被带上 _ENV
local i = 10
j = 100
k = j + i
print(i, j, k)
会被转换为
local i = 10
_ENV.j = 100
_ENV.k = _ENV.j + i
print(i, _ENV.j, _ENV.k)
对于上面的代码段, _ENV 的存在点,可以理解为如下
local _ENV = 初始化
return function (...)
local i = 10
_ENV.j = 100
_ENV.k = _ENV.j + i
print(i, _ENV.j, _ENV.k)
end
这里可以注意到 _ENV
是一个代码段外部的局部变量 ,但是他会进行初始化,理论上他可以是任意的表,但是为了维护全局的概念,所以这里会使用 _G
进行初始化,这样就让我们无感知的使用到了全局。
我们可以将 _ENV 和 _G 进行打印,在不进行修改的情况下,_ENV 和 _G 两者其实都是同一个表
do
print(_ENV, _G) --> table: 0x6000007d4200 table: 0x6000007d4200
end
1-1、为什么要 _G._G = _G
前面提及到 _G 表中有一个 _G 字段指向自身,即 _G._G = _G
,这是为了能达到以下效果
_G.name = "jiang peng yong"