一 环境 Environment
(1) 默认的_G有什么
lua语言将'全局环境自身'保存在'全局变量_G' --> _G._G <="等价"=> _G
备注:输出的结果来看有一个'_G',也'印证'了这一点
_G也是一张'普通(common)的表'
这个表'保存'了lua所有的'全局函数'和'全局变量'
(2)lua5.1
1. lua将'环境表'保存在一个'全局变量_G'中,可以对其'访问'和'设置'
备注:5.2之前还'没有_ENV'的概念,only有'_G'
2. 一般我们把需要'被访问'的'对象(变量)'和'函数'等放到这里,然后可以在'需要时'通过它来访问和使用
3. 可以通过value = _G["varname"]或者value = _G.varname来获得'动态'名字的全局变量
1)等价形式
2)改变环境
lua5.1"允许"每个函数拥有一个'子集的环境'来查找"全局变量",可以通过'setfenv'来改变一个函数的环境
语法:setenv(func or number,table),第一个参数可以是'数字'也可以是'函数'
--1. 第'一'个参数若是"1"则表示当前函数,"2"则表示调用'当前函数'的函数 -->'依次类推'
--2. 第'二'个参数是一个'新的环境'table
功能:setenv是在lua5.1中'改变函数作用域'的函数
强调:只有'设置了'setfenv了环境,getfenv才能'生效'
补充:'了解'即可
(3)lua5.2+
5.2版本: '_G'是'_ENV中'的一个'key'
在5.2中: 操作a = 1"相当于"_ENV['a'] = 1
注意:5.2+没有'setfenv'
1)只有全局变量才注册到_G
(4)应用
① 检测所有对全局表中不存在键的访问
解读: 所有'试图'对'不存在全局变量'的访问都将'引发'一个'error错误'
② 判断一个变量是否存在
二 非全局环境
要点: Lua语言'本质'上没有'全局变量',因此"_ENV"'不是'全局变量,而是一个upvalue'非局部变量'
① 概念
② 自有名称
概念: '没有关联'到显示声明上的名称,即它'不出现'在对应'局部变量'的范围内
简单理解:想对而言的'全局变量'
③ 编译器处理机制
1. lua语言把'所有的代码段'都当作'匿名函数'
④ _ENV
1. _ENV的"初始值"可以是'任意的值',一般是'表table'
2. 任何一个'这样的表'被称之为'一个环境' -->"重点!!!"
3. Lua语言在'内部维护'了一个表来用作'全局环境'
⑤ lua语言中处理全局变量的规则
1. 前'两个规则'完全由编译器'预先定义'的
1)函数load
1. load的'本质'就是在Lua代码中'运行'一段存储在'字符串中的代码'
2. load有'另一层'含义,它是将字符串的内容作为一个'函数体返回'
当加载一个"代码段"时,函数会使用'预定义'的upvalue["上值"]来初始化环境
关注: _ENV变量的值的'由来'
细细体会: 有点'闭包'的味道
三 使用_ENV
说明: 主要是掌握从'上面三条规则'引申出来的一些'技巧'
_ENV'引用'的是其'所在位置'所有'可见'的_ENV变量
① _ENV只是一个普通变量
1. 可以'赋值'
2. 可以'访问'
3. 改变'代码段'使用的环境 <-- "_ENV的用途"
备注:通过'覆盖_ENV变量'设置一个'全新的环境'
效果: 任何对'自由'名称"全局变量"的赋值都会引发'类似的错误'
② 显示使用_ENV绕过局部声明
③ 案例
+++++++++++++"三者结果一致"+++++++++++++
print(_ENV);
print(_ENV._G);
print(_G);
⑤ 案例
1)将当前环境变为空表
注意:如果'新环境'是空的,会'丢失'之前所有的"全局变量"
2)如何访问全局变量a
⑥ 补充_G和_ENV的区别
注意: _ENV和_G的'调用' -->"_G"只是"_ENV"的一个键,只有在刚'初始化'的时候"_G==_ENV"
⑦ 继承的方式使用旧环境
⑧ _ENV关于函数
1)案例1
2)案例2
局部'_ENV'
3)案例三
使用'私有环境'定义一个函数
每个'闭包'都会使用'自己的外部变量-->ENV(_upvalue)'来访问其'自由名称'
四 环境和模块
了解即可: 个人倾向于'原始M.add'的方法
特点:模块的'主程序块'有一个'独占'的环境,该模块所有的函数'共享'这个环境
优点:在'调用'时,'不需要'任何'前缀'
五 luajit
1. lua 5.1和5.2是个'分水岭'
2. luajit'只支持'5.1,介于luajit的'卓越性能'[快速、代码编译、ffi等],使用luajit的'不要去学'lua5.2
核心:openresty就是'基于'luajit,扩展了一些'新特性' --> openresty还得'参照'5.1
①②③④⑤⑥⑦⑧⑨⑩