在Lua中,为未声明的变量分配未定义的标识符意味着什么?

时间:2010-10-16 15:40:16

标签: lua world-of-warcraft

我正在阅读Lua代码文件,文件的最顶部包含:

    1  | TradeSkillFrameReset = TradeSkillFrame_LoadUI;
    2  | 
    3  | TradeSkillFrame_LoadUI = function()
    4  |    TradeSkillFrameReset();
            ...
    112|    TradeSkillFrame_LoadUI = TradeSkillFrameReset;
            ...
    114| end;

他们正在完成任务的第一行:

TradeSkillFrameReset = TradeSkillFrame_LoadUI;

此时,在代码文件中,他们将未声明的标识符(TradeSkillFrame_LoadUI)分配给未声明的变量(TradeSkillFrameReset)。 Lua允许这样做吗?

  • 是隐式的变量声明吗?
  • 是假定为前向声明的所有未声明的标识符吗?

更令人困惑的是,第一个TradeSkillFrame_LoadUI似乎做的就是召唤自己:

TradeSkillFrame_LoadUI = function()
   TradeSkillFrameReset();

这怎么不是无限循环?


修改:添加了对TradeSkillFrameResetTradeSkillFrame_LoadUI的剩余引用。

5 个答案:

答案 0 :(得分:5)

如果TradeSkillFrame_LoadUI是全局函数,则第一个语句在TradeSkillFrameReset中捕获此函数。

TradeSkillFrame_LoadUI的分配然后用新的函数替换全局函数,该函数首先通过TradeSkillFrameReset引用调用原始函数。

这种模式被称为“函数挂钩”,here是关于一般技术和一些魔兽世界Lua环境特定细节的更多信息(这个脚本可能来自,根据函数的名称)

一些示例代码,为了清楚说明:

function SomeGlobalFunction()
    print("I'm the original global function")
end

OrigFunction = SomeGlobalFunction

SomeGlobalFunction = function()
    OrigFunction()
    print("And here's the modfied one...")
end

--...
SomeGlobalFunction()

这将打印以下输出:

  

我是原始的全球职能

     

这是修改过的......

作为旁注,Lua的名字是not all capitalized

答案 1 :(得分:0)

在第一行,由于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上更改它。

如果这还不够明确,请告诉我。

答案 2 :(得分:0)

除非在您正在使用的环境中修改了全局变量的行为,否则该语句绝对没有任何内容。

local TradeSkillFrameReset = TradeSkillFrame_LoadUI

会产生影响,创建一个局部变量“slot”并使代码超过该点使用TradeSkillFrameReset的局部变量槽而不是为它进行全局变量查找。但是,正如你发布的代码一样,它只是将全局变量赋值为nil,这样就可以删除它,换句话说,如果它已经为零则没有效果。

可能存在的原因:

1)运行代码的环境在完成全局变量赋值时会执行一些特殊操作,而不是简单赋值的默认行为。我不认为这很可能,好像有任何特殊行为,查找nil TradeSkillFrame_LoadUI可能会导致错误。

2)最可能的原因仅仅是为了可读性。这是为了让您知道TradeSkillFrameReset 正确分配给以后隐藏在代码中的某个地方,您将不会轻易注意到它。

答案 3 :(得分:0)

最重要的是Lua代码很容易将全局变量注入到其他Lua代码中。我已经使用了很多Lua,他们使用环境来添加全局变量。仅仅因为没有在该文件中定义var,最肯定的并不意味着它不存在。它甚至不必被定义为另一个文件中的全局变量,因为您可以以编程方式注入环境表,就像它是任何其他表一样。

答案 4 :(得分:-1)

我猜它会做类似于Javascript函数提升的东西,你可以在这里阅读:Referencing a JavaScript value before it is declared - can someone explain this