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
参照。
このパターンは「関数フッキング」と呼ばれ、 ここ 一般的なテクニックとWorld of Warcraft 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()
これにより、次の出力が印刷されます。
私は元のグローバル機能です
そして、これがmodfiedのものです...
サイドノートとして、ルアの名前はです すべてが資本化されているわけではありません.
他のヒント
それ以来、最初の行に 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
ローカル変数の「スロット」を作成し、そのポイントを過ぎてコードを作成する効果があり、グローバル変数検索を行うのではなく、cordeskillframeresetにローカル変数スロットを使用します。ただし、投稿したコードにあるように、グローバル変数をNILに割り当てるだけです。これは、それを消去する効果があります。つまり、すでにnilであれば効果はありません。
それがそこにある可能性がある理由:
1)コードが実行されている環境は、単純な割り当てのデフォルトの動作ではなく、グローバル変数割り当てが完了した場合、特別なことを行います。しかし、これはおそらくそうではないと思います。まるで特別な動作があったかのように、nil cordeskillframe_loaduiの検索がおそらくエラーを引き起こすでしょう。
2)最も可能性の高い理由は、単に読みやすさのためです。それはあなたにそのcordeskillframeresetを知らせることです 意思 コードのどこかに埋葬された後で埋葬された後で適切に割り当てられます。
奪う主なことは、LUAコードがグローバル変数を他のLUAコードに挿入するのが簡単であることです。私は多くのLUAを使用して、環境を使用してグローバルなVARを追加しました。 VARがそのファイルで最も確実に定義されていないからといって、それが存在しないという意味ではありません。別のファイルのグローバル変数として定義する必要さえありません。これは、環境テーブルにプログラムで他のテーブルであるかのように注入できるためです。
JavaScriptの関数が巻かれていることに似たことをしていると思います。ここで読むことができます。 JavaScript値が宣言される前に参照する - 誰かがこれを説明できますか