对于深度嵌套表中的字段,例如 text.title.1.font。即使你使用
if text.title.1.font then ... end
如果表的任何级别实际上不存在,它将导致类似“尝试索引全局'文本'(零值)”的错误。当然,可能会尝试检查表的每一级是否存在,但这似乎相当麻烦。我想知道是否有一种安全且更漂亮的方法来处理这个问题,这样当引用这样的对象时,nil 将是值而不是触发错误?
对于深度嵌套表中的字段,例如 text.title.1.font。即使你使用
if text.title.1.font then ... end
如果表的任何级别实际上不存在,它将导致类似“尝试索引全局'文本'(零值)”的错误。当然,可能会尝试检查表的每一级是否存在,但这似乎相当麻烦。我想知道是否有一种安全且更漂亮的方法来处理这个问题,这样当引用这样的对象时,nil 将是值而不是触发错误?
Egor 的建议debug.setmetatable(nil, {__index = function()end})
是最容易应用的。请记住,它不是词法范围的,因此,一旦打开,它将一直处于“打开”状态,直到关闭,这可能会对代码的其他部分产生意想不到的后果。有关讨论和一些替代方案,请参见此线程。
还要注意text.title.1.font
应该是text.title[1].font
or text.title['1'].font
(而且这两个不一样)。
另一个更冗长但仍然可用的替代方法是:
if (((text or {}).title or {})[1] or {}).font then ... end
这样做不会引起很多错误的方法是明确告诉 Lua 哪些表的哪些字段默认应该是表。您可以使用元表来做到这一点。以下是一个示例,但实际上应该根据您希望表格的结构对其进行自定义。
-- This metatable is intended to catch bugs by keeping default tables empty.
local default_mt = {
__newindex =
function()
error(
'This is a default table. You have to make nested tables the old-fashioned way.')
end
}
local number_mt = {
__index =
function(self, key)
if type(key) == 'number' then
return setmetatable({}, default_mt)
end
end
}
local default_number_mt = {
__index = number_mt.__index,
__newindex = default_mt.__newindex
}
local title_mt = {__index = {title = setmetatable({}, default_number_mt)}}
local text = setmetatable({}, title_mt)
print(text.title[1].font)