目录
1.load
同loadstring,5.2版本之后loadstring被移除,用load代替
load(chunk, chunkname, mode, env) 用于加载字符串代码块,参数如下:
chunk | 字符串代码块 |
chunkname | 模块名,默认是"chunk",当使用assert函数报错后会被打印出来 |
mode | 文件类型:"b":二进制;"t":文本文件;"bt":同时兼容二进制和文本文件,不填默认是"bt" |
env | 环境变量,不填默认会用_ENV填充,附带lua标准类库 |
这里要注意:load用于加载字符串代码块并编译,但是并没有运行。在使用前要记得运行一下,参见如下:
a = 100
--加载字符串代码块
f = assert(load("a = a + 100"))
print("before a = "..a)
--运行代码块
f()
print("after a = "..a)
输出如下:
before a = 100
after a = 200
可以看到加载代码块后,在没有运行前,a的值没有发生变化为100,运行后执行了a = a + 100,a = 200
1.代码块chuck如何理解?
lua中的代码块chunk,实际编译的时候,相当于被一个可变参匿名函数包装,并且会绑定一个唯一的upvalue值_ENV,运行后将代码块chunk中的全局变量添加到了全局环境变量_ENV中。代码块 "a = a + 100" 相当于如下函数:
--代码块
function chuck()
a = a + 100
end
--这句是比喻load代码块的加载编译过程(不一定恰当,意会就好)
f = chuck()
--运行
f()
2.这里有些同学可能会疑惑,load中的这段代码块为什么能访问到外部的变量a?
env:它是一个环境变量,可以自定义(一般用于模拟一个沙盒环境),默认这个值会用lua的全局环境变量_ENV填充。
_ENV是lua5.2版本才有的用来代替_G的一个全局变量(_ENV内部是指向_G的,可以简单的认为他们是同一个东西),但它是一个upvalue值。(_G及_ENV感兴趣的可以自行了解)这里简单描述一下_ENV,每一个lua代码块默认都会有一个_ENV全局环境变量,它是一个表,包含了所有的lua标准类库及所有编译过的全局变量。
参见如下:
a = 100
--加载并运行字符串代码块
assert(load("a = a + 11; b = 'b126'; print('this is chunk')"))()
print("a = "..a)
print("_ENV.a = ".._ENV.a)
print("b = "..b)
print("_ENV.b = ".._ENV.b)
输出如下:
this is chunk
a = 111
_ENV.a = 111
b = b126
_ENV.b = b126
可以看到:
1) 代码块中,可以调用print函数,这就是因为默认env传入的是_ENV,相当于调用_ENV.print
2) a 和 _ENV.a 输出相同,其实在编译的时候,全局变量默认都会在前面加一个_ENV.限定
3) 编译并运行代码块chunk后,变量b已被加入到_ENV中
3.自定义环境变量env的使用
一般用于模拟一个沙盒环境,参见如下:
a = 100
--自定义环境变量
local env = {
a = 8,
print = print
}
--加载并运行字符串代码块
assert(load("a = a + 10; print('this is chunk, a = '..a)", "chunkTest", "bt", env))()
print("a = "..a)
输出如下:
this is chunk, a = 18
a = 100
1) 可以看到代码块chunkTest中,a取的是自定义环境变量env的a值,打印a = 18;
2) 因为这里没有用默认全局环境变量_ENV填充,所以外部变量 a 并没有被修改: a = 100
3) env中的 print = print,等价于:print = _ENV.print
2.loadfile
loadfile(filename, mode, env) 用于加载一个指定路径filename的代码块,参数如下:
filename | 文件的加载路径,要包含文件后缀 |
mode | 文件类型:"b":二进制;"t":文本文件;"bt":同时兼容二进制和文本文件,不填默认是"bt" |
env | 环境变量,不填默认会用_ENV填充,附带lua标准类库 |
基本和load等同,区别是用来加载一个文件的代码块,参见如下:
LuaFunc.lua(被访问)文件:
--LuaFunc.lua
function add(x, y)
return x + y
end
m = "LuaFunc.m"
local n = "n"
print("------------------ < LuaFunc.lua > ------------------")
print("m = "..m)
print("n = "..n)
print("------------------ < LuaFunc.lua > ------------------")
调用代码如下:
--加载并编译代码
f = assert(loadfile("Child/LuaFunc.lua"))
--运行
f()
print("add : "..add(100, 88))
print(m)
输出如下:
------------------ < LuaFunc.lua > ------------------
m = LuaFunc.m
n = n
------------------ < LuaFunc.lua > ------------------
add : 188
LuaFunc.m
3.dofile
dofile(filename) 用于加载一个指定路径filename的代码块,并运行。参数如下:
filename | 文件的加载路径,要包含文件后缀 |
内部先调用了loadfile,然后会自动运行一下,参见如下:
dofile("Child/LuaFunc.lua")
print("add : "..add(100, 88))
print(m)
输出与上例等同
4.require
require(modname) 用于加载一个指定的代码块,并运行。参数如下:
modname | 文件名,不包含后缀 |
这个函数对于同一个代码块只会加载一次(加载过会保存起来),和dofile类似,加载编译后也会自动运行,参见如下:
--加载编译并运行
require("Child/LuaFunc") -- 等同于:require("Child.LuaFunc")
print("add : "..add(100, 88))
print(m)
输出同上例