Lua將其所有的全局變量保存在一個常規(guī)的table中,這個table被稱為“環(huán)境”。它被保存在全局變量_G中。
1. 全局變量聲明:
Lua中的全局變量不需要聲明就可以使用。盡管很方便,但是一旦出現(xiàn)筆誤就會造成難以發(fā)現(xiàn)的錯誤。我們可以通過給_G表加元表的方式來保護(hù)全局變量的讀取和設(shè)置,這樣就能降低這種筆誤問題的發(fā)生幾率了。見如下示例代碼:
a = 11
local kk = aa
--輸出結(jié)果為:
--[[
Setting a to 11
lua: d:/test.lua:21: attempt to read undeclared variable aa
stack traceback:
[C]: in function 'error'
d:/test.lua:21: in function <d:/test.lua:19>
d:/test.lua:30: in main chunk
[C]: ?
--]]
2. 非全局的環(huán)境:
全局環(huán)境存在一個剛性的問題,即它的修改將影響到程序的所有部分。Lua 5為此做了一些改進(jìn),新的特征可以支持每個函數(shù)擁有自己獨(dú)立的全局環(huán)境,而由該函數(shù)創(chuàng)建的closure函數(shù)將繼承該函數(shù)的全局變量表。這里我們可以通過setfenv函數(shù)來改變一個函數(shù)的環(huán)境,該函數(shù)接受兩個參數(shù),一個是函數(shù)名,另一個是新的環(huán)境table。第一個參數(shù)除了函數(shù)名本身,還可以指定為一個數(shù)字,以表示當(dāng)前函數(shù)調(diào)用棧中的層數(shù)。數(shù)字1表示當(dāng)前函數(shù),2表示它的調(diào)用函數(shù),以此類推。見如下代碼:
--輸出結(jié)果為:
--[[
lua: d:/test.lua:3: attempt to call global 'print' (a nil value)
stack traceback:
d:/test.lua:3: in main chunk
[C]: ?
--]]
為什么得到這樣的結(jié)果呢?因為print和變量a一樣,都是全局表中的字段,而新的全局表是空的,所以print調(diào)用將會報錯。
為了應(yīng)對這一副作用,我們可以讓原有的全局表_G作為新全局表的內(nèi)部表,在訪問已有全局變量時,可以直接轉(zhuǎn)到_G中的字段,而對于新的全局字段,則保留在新的全局表中。這樣即便是函數(shù)中的誤修改,也不會影響到其他用到全局變量(_G)的地方。見如下代碼:
a = 10
print(a) --輸出10
print(_G.a) --輸出1
_G.a = 20
print(a) --輸出10
最后給出的示例是函數(shù)環(huán)境變量的繼承性。見如下代碼:
setfenv(f1,{a = 10})
print(f1()) --輸出10
print(f2()) --輸出3
新聞熱點(diǎn)
疑難解答
圖片精選