local M = {} local modname = 'a' _G[modname] = M package.loaded[modname] = M function M.play() print('play') end function M.say() print('say') M.play() end return M
这里的问题是模块内函数之间的调用仍然要保留模块名的限定符,好比say中调用play方法就须要M.play。函数
解决上面那个问题能够用setfenv把当前模块的全局环境设置为M,因而,定义函数的时候就不用加上M,模块中函数间的调用也不须要加M限定。lua
local M = {} local modname = 'a' _G[modname] = M package.loaded[modname] = M setfenv(1, M) function play() -- print('play') end function say() -- print('say') play() end return M
上面把print注释掉了,是由于这个时候调用play或者say方法会报错,大概是说没有print这个东西。由于当前的全局环境变了,不是_G而是M,M中固然没有print。那要如何使用到_G中的全局变量呢?元表。code
local M = {} local modname = 'a' _G[modname] = M package.loaded[modname] = M setmetatable(M, {__index = _G}) setfenv(1, M)
能够使用module函数来替换下面的代码io
local M = {} local modname = 'a' _G[modname] = M package.loaded[modname] = M setfenv(1, M)
上面的能够简化为table
module('a')
module默认是不提供外部访问的,也就是说这个时候print这些仍是不能用的。function
若是要加上setmetatable(M, {__index = _G})
的效果,须要加上package.seeall
参数,如class
module('a', package.seeall)
稍微一个总结:使用module来建立模块,定义函数以及模块内函数间的调用均可以不用加上限定附,好比上面的M。还有就是能够不用写return M,以及能够访问到_G中的全局变量。变量
附:module
setfenv(f, table):设置一个函数的环境meta
(1)当第一个参数为一个函数时,表示设置该函数的环境
(2)当第一个参数为一个数字时,为1表明当前函数,2表明调用本身的函数,3表明调用本身的函数的函数,以此类推
所谓函数的环境,其实一个环境就是一个表,该函数被限定为只能访问该表中的域,或在函数体内本身定义的变量。