文章來之:http://www.myexception.cn/mobile/1439151.html javascript
理解Lua語言中的__index,__newindex,rawget和rawset
html
在談及Lua中的__index,__newindex,rawget和rawset前,須要理解Lua中的元表這個概念。java
對Lua中元表的解釋: 元表能夠改變表的行爲模式。ide
這裏舉個例子:函數
Window = {} Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,} Window.mt = {} function Window.new(o) setmetatable(o ,Window.mt) return o end Window.mt.__index = Window.prototype Window.mt.__newindex = function (table ,key ,value) if key == "wangbin" then rawset(table ,"wangbin" ,"yes,i am") end end w = Window.new{x = 10 ,y = 20} w.wangbin = "55" print(w.wangbin)
而後,咱們能夠看到打印信息是:yes,i amlua
本來賦值的地方是w.wangbin = "55",可是結果倒是 yes,i am。spa
這裏就改變了元表的行爲模式。prototype
__index是:當咱們訪問一個表中的元素不存在時,則會觸發去尋找__index元方法,若是不存在,則返回nil,若是存在,則返回結果。code
Window = {} Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,} Window.mt = {} function Window.new(o) setmetatable(o ,Window.mt) return o end Window.mt.__index = function (t ,key) -- body return 1000 end w = Window.new{x = 10 ,y = 20} print(w.wangbin)
打印結果是:1000。這裏能夠看出,咱們在new的時候,w這個表裏其實沒有wangbin這個元素的,咱們重寫了元表中的__index,使其返回1000,意思是:若是你要尋找的元素,該表中沒有,那麼默認返回1000。orm
__newindex:當給你的表中不存在的值進行賦值時,lua解釋器則會尋找__newindex元方法,發現存在該方法,則執行該方法進行賦值,注意,是使用rawset來進行賦值,至於緣由,後面會講到。
Window.mt = {} function Window.new(o) setmetatable(o ,Window.mt) return o end Window.mt.__index = function (t ,key) return 1000 end Window.mt.__newindex = function (table ,key ,value) if key == "wangbin" then rawset(table ,"wangbin" ,"yes,i am") end end w = Window.new{x = 10 ,y = 20} w.wangbin = "55" print(w.wangbin)
ok,這裏的打印結果是:yes,i am。w這個表裏原本沒有wangbin這個元素的,咱們重寫了元表中__newindex,並在__newindex方法中從新進行賦值操做,而後,咱們對這個本不存在的原色w.wangbin進行賦值時,執行__newindex方法的賦值操做,最後,打印結果即是:yes,i am
rawget是爲了繞過__index而出現的,直接點,就是讓__index方法的重寫無效。(我這裏用到"重寫"二字,可能不太對,但願能獲得糾正)
Window = {} Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,} Window.mt = {} function Window.new(o) setmetatable(o ,Window.mt) return o end Window.mt.__index = function (t ,key) return 1000 end Window.mt.__newindex = function (table ,key ,value) if key == "wangbin" then rawset(table ,"wangbin" ,"yes,i am") end end w = Window.new{x = 10 ,y = 20} print(rawget(w ,w.wangbin))
打印結果是:nil。這裏的元表中__index函數就再也不起做用了。
可是rawset呢,起什麼做用呢?咱們再來運行一段代碼。
Window = {} Window.prototype = {x = 0 ,y = 0 ,width = 100 ,height = 100,} Window.mt = {} function Window.new(o) setmetatable(o ,Window.mt) return o end Window.mt.__index = function (t ,key) return 1000 end Window.mt.__newindex = function (table ,key ,value) table.key = "yes,i am" end w = Window.new{x = 10 ,y = 20} w.wangbin = "55"
而後咱們的程序就stack overflow了。可見,程序陷入了死循環。由於w.wangbin這個元素原本就不存在表中,而後這裏不斷執行進入__newindex,陷入了死循環。