在LUA中,将未定义的标识符分配给未确定的变量是什么意思?
-
08-10-2019 - |
题
我正在仔细阅读LUA代码文件,文件的顶部包含:
1 | TradeSkillFrameReset = TradeSkillFrame_LoadUI; 2 | 3 | TradeSkillFrame_LoadUI = function() 4 | TradeSkillFrameReset(); ... 112| TradeSkillFrame_LoadUI = TradeSkillFrameReset; ... 114| end;
他们正在做任务的第一行:
TradeSkillFrameReset = TradeSkillFrame_LoadUI;
在代码文件中的这一点上,他们分配了未销售的标识符(TradeSkillFrame_LoadUI
)到未宣布的变量(TradeSkillFrameReset
)。这在卢阿允许吗?
- 变量声明是隐式的吗?
- 是否都认为所有未申报的标识符是正向声明?
更令人困惑的是第一个 TradeSkillFrame_LoadUI
似乎要做的就是呼唤自己:
TradeSkillFrame_LoadUI = function()
TradeSkillFrameReset();
这不是无限循环?
编辑: 添加了剩余的参考 TradeSkillFrameReset
和 TradeSkillFrame_LoadUI
.
解决方案
如果 TradeSkillFrame_LoadUI
是全局函数,第一个语句在 TradeSkillFrameReset
.
对 TradeSkillFrame_LoadUI
然后用新功能替换全局函数,该功能首先通过 TradeSkillFrameReset
参考。
该模式称为“函数钩”, 这里 是有关通用技术的更多信息和魔兽世界的某些世界特定细节(根据该功能的名称,该脚本可能来自何处)
一些示例代码,以说明这一点:
function SomeGlobalFunction()
print("I'm the original global function")
end
OrigFunction = SomeGlobalFunction
SomeGlobalFunction = function()
OrigFunction()
print("And here's the modfied one...")
end
--...
SomeGlobalFunction()
这将打印以下输出:
我是原始的全球功能
这是一个适应的人...
旁注,卢阿的名字是 并非全部大写.
其他提示
在第一行,自 TradeSkillFrame_LoadUI
是一个非初始化的变量,然后是第一行:
TradeSkillFrameReset = TradeSkillFrame_LoadUI;
与制作相同:
TradeSkillFrameReset = nil
下面的功能不会进入无限循环,因为Tradeskillframereset实际上并没有“指向任何东西”。
我的猜测是,在代码后来,它得到了正确初始化的。像这样:
TradeSkillFrameReset = TradeSkillFrame_LoadUI;
TradeSkillFrame_LoadUI = function() -- 1. function declaration
TradeSkillFrameReset();
[...snip...]
end;
[... snip ...]
TradeSkillFrameReset = somethingElse -- 2. initialized to something else
TradeSkillFrame_LoadUI() -- 3. function invocation
诀窍是您可以在1上定义一个函数,并在3上更改2上的变量值。
让我知道这是否还不够清晰。
除非在您使用的环境中修改了全局变量的行为,否则该语句绝对没有任何作用。
local TradeSkillFrameReset = TradeSkillFrame_LoadUI
会产生效果,创建一个局部变量的“插槽”,并使代码超过该点,将局部变量插槽用于TradeSkillFramerEset,而不是为其进行全局变量查找。但是,正如您发布的代码中一样,它只是将全局变量分配给nil,换句话说,它的效果是将其删除,如果它已经是零,则不会效果。
理由可能存在:
1)当完成全局变量分配时,代码正在运行的环境会做一些特别的事情,而不是简单分配的默认行为。我认为这不可能,好像有任何特殊行为一样,nil Tradeskillframe_loadui的查找可能会导致错误。
2)最可能的原因仅仅是出于可读性。这是为了让您知道Tradeskillframereset 将要 正确地分配给后来埋葬在代码中的某个地方,您将不会随时注意到它。
最主要的是,LUA代码很容易将全局变量注入其他LUA代码。我使用了很多LUA,他们使用环境来添加全局var。仅仅因为该文件中未定义的var并不意味着它不存在。甚至不必将其定义为另一个文件中的全局变量,因为您可以通过编程表,就像其他表一样,以编程为单位。
我猜想它做的类似于JavaScript的功能提升的操作,您可以在这里阅读: 在声明javascript值之前引用javascript值 - 有人可以解释一下