Lua rawset、rawget
如果对一个表查找的时候,若表中不存在该值,则会查找该表的元表,访问其元表 __index 字段来获取
如果对一个表添加新索引键,则会查找该表的元表访问其元表 __newindex 字段来添加
而 rawset、rawget 则是绕过元表这一过程
rawget(table, index)
在不触发任何元表方法的情况下,获取 table[index] 的值,table 必须是一张表,index 可以是任何值
rawset(table, index, value)
在不触发任何元方法的情况下将 table[index] 赋值为 value,而 table 必须是一张表, index 可以是 nil 与 NAN 之外的任何值,value 可以是任何 Lua 值
什么时候使用
当操作table时,如果我们有以下需求:
取值访问时,不想从 __index 对应的元方法中查询值,使用 rawget
赋值更新时,不想执行 __newindex 对应的元方法,使用 rawset
在 __newindex 元方法中,设置table的key/value时,不想陷入死循环而爆栈
当获取表中一个索引键对应的值时(local value = table.key),可以使用 rawget 函数,调用 rawget (table, key) 就是对table 进行了一次“原始的(raw)”访问,也就是一次不考虑元表的简单访问;
当需要向表添加一个索引键时(table.key= 5),对于__newindex元方法,可以调用rawset(table, key, value)函数,它可以不涉及任何元方法而直接设置table中与key相关联的value
你可能会想,一次原始的访问,没有访问__index对应的元方法,可能有性能的提升,其实一次原始访问并不会加速代码执行的速度。
local biology = { breathe = true }
local animation = { leg = 4}
local bird = { color = "red"}
setmetatable(bird, { __index = biology, __newindex = animation })
print("bird.breathe:"..tostring(bird.breathe))
-- 输出:bird.breathe:true
-- breathe 继承与 biology
-- 通过 rawget 获取 表 bird 的索引建 color
local color = rawget(bird, "color")
print("color:"..tostring(color))
bird.name = "parrot"
-- 通过 __newindex 将新索引键 name 赋值给 animation
print("bird.name:"..tostring(bird.name))
-- 输出:bird.name:nil
print("animation.name:"..animation.name)
-- 输出:animation.name:parrot
-- 所以现在想通过 bird.name = "xxx" 添加新索引键已经无法添加了
-- 通过 rawset 给 bird 添加索引键
rawset(bird, "abc", 5)
local abc = bird.abc
print("bird.abc:"..tostring(abc))