目录
1.load
2.loadfile
3.dofile
4.require
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用于加载字符串代码块并编译,但是并没有运行。在使用前要记得运行一下,参见如下:
1 2 3 4 5 6 7 | a = 100 --加载字符串代码块 f = assert(load("a = a + 100")) print("before a = "..a) --运行代码块 f() print("after a = "..a) |
输出如下:
1 2 | before a = 100 after a = 200 |
可以看到加载代码块后,在没有运行前,a的值没有发生变化为100,运行后执行了a = a + 100,a = 200
1.代码块chuck如何理解?
lua中的代码块chunk,实际编译的时候,相当于被一个可变参匿名函数包装,并且会绑定一个唯一的upvalue值_ENV,运行后将代码块chunk中的全局变量添加到了全局环境变量_ENV中。代码块 "a = a + 100" 相当于如下函数:
1 2 3 4 5 6 7 8 | --代码块 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标准类库及所有编译过的全局变量。
参见如下:
1 2 3 4 5 6 7 | 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) |
输出如下:
1 2 3 4 5 | 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的使用
一般用于模拟一个沙盒环境,参见如下:
1 2 3 4 5 6 7 8 9 | 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) |
输出如下:
1 2 | 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(被访问)文件:
1 2 3 4 5 6 7 8 9 10 11 12 | --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 > ------------------") |
调用代码如下:
1 2 3 4 5 6 | --加载并编译代码 f = assert(loadfile("Child/LuaFunc.lua")) --运行 f() print("add : "..add(100, 88)) print(m) |
输出如下:
1 2 3 4 5 6 | ------------------ < LuaFunc.lua > ------------------ m = LuaFunc.m n = n ------------------ < LuaFunc.lua > ------------------ add : 188 LuaFunc.m |
3.dofile
dofile(filename) 用于加载一个指定路径filename的代码块,并运行。参数如下:
| filename | 文件的加载路径,要包含文件后缀 |
内部先调用了loadfile,然后会自动运行一下,参见如下:
1 2 3 | dofile("Child/LuaFunc.lua") print("add : "..add(100, 88)) print(m) |
输出与上例等同
4.require
require(modname) 用于加载一个指定的代码块,并运行。参数如下:
| modname | 文件名,不包含后缀 |
这个函数对于同一个代码块只会加载一次(加载过会保存起来),和dofile类似,加载编译后也会自动运行,参见如下:
1 2 3 4 | --加载编译并运行 require("Child/LuaFunc") -- 等同于:require("Child.LuaFunc") print("add : "..add(100, 88)) print(m) |
输出同上例