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表明調用本身的函數的函數,以此類推
所謂函數的環境,其實一個環境就是一個表,該函數被限定爲只能訪問該表中的域,或在函數體內本身定義的變量。