当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键。如果__index包含一个表格,Lua会在表格中查找相应的键。
1 tabMETA ={ temp = 1} 2 3 tabA = setmetatable( {} ,{ __index = tabMETA} ); 4 5 print(tabA.temp) 6 7 输出: 1
如果__index包含一个函数的话,Lua就会调用那个函数,table和键会作为参数传递给函数。
__index 元方法查看表中元素是否存在,如果不存在,返回结果为 nil;如果存在则由 __index 返回结果。
1 mytable = setmetatable({key1 = "value1"}, { __index = { key2 = "metatablevalue" } }) 2 print(mytable.key1,mytable.key2) 3 4 输出:value1 metatablevalue
注意!
Lua 查找一个表元素时的规则,其实就是如下 3 个步骤:
- 1.在表中查找,如果找到,返回该元素,找不到则继续
- 2.判断该表是否有元表,如果没有元表,返回 nil,有元表则继续。
- 3.判断元表有没有 __index 方法,如果 __index 方法为 nil,则返回 nil;如果 __index 方法是一个表,则重复 1、2、3;如果 __index 方法是一个函数,则返回该函数的返回值。
该部分内容来自作者寰子:https://blog.csdn.net/xocoder/article/details/9028347
__newindex 元方法用来对表更新,__index则用来对表访问 。
如果你尝试给一个不存在的索引进行赋值,解释器就会查找__newindex 元方法:如果是函数则调用这个函数而不进行赋值操作。
1 tab = setmetatable({},{__newindex= function(tab,key,value) print("注意:尝试给不存在的索引赋值!") end}) 2 tab[1] = 1 --给不存在的索引赋值 3 print(tab[1]) 4 5 输出: 注意:尝试给不存在的索引赋值! nil
但是,如果我想要进行赋值操作该怎么办呢?
是这样写吗?
1 tab = setmetatable({},{function(tab,key,value) 2 tab[key] = value 3 end})
上述写法是错误的,会导致栈溢出,原因是因为函数中的“tab[key] = value”在执行时,又会调用该表的__newindex元方法,一层一层的无限调用下去,导致栈溢出。
正确写法如下:
1 tab = setmetatable({},{function(tab,key,value) 2 rawset(tab,key,value) 3 end})
这里用了rawset函数来赋值,rawset的参数为(表,键,值) rawset(tab,key,value)
如果你尝试给一个不存在的索引进行赋值,解释器就会查找__newindex 元方法:如果是表则在此表中赋值,不对原表进行操作。
1 tab2 = {}
2 tab1 = setmetatable({},{__newindex = tab2})
3 tab1[996]="不要996"
4 print(tab1[996])
5 print(tab2[996])
6
7 输出:nil 不要996 --出现在了tab2中
原文:https://www.cnblogs.com/guoyujam/p/12199378.html