Lua言語は、グローバル環境自体をグローバル変数_Gに保存し、グローバル環境内のすべてのグローバル変数の名前を次のように出力します。
ペアのnの場合(_G)印刷(n)終了
- 動的な名前を持つグローバル変数
別の変数のグローバル変数の取得、
value = load( "return" .. varname)()和
value = _G [varname]も同じ効果があり、後者の方が1桁効率的です。
- グローバル変数宣言
次のように、グローバル変数を宣言なしで使用して、グローバルテーブルの存在しないすべてのアクセスを検出できます。
setmetatable(_G,{
__newindex = function (_,n)
error("attempt to write to undeclared varibale "..n,2)
end,
__index = function (_,n)
error("attempt to read to undeclared varibale "..n,2)
end,
})
もちろん、rawsetとrawgetを使用してメタメソッドをバイパスすることもできます。
- 非グローバル変数
次のようなフリーネーム(フリーネーム):xは_ENV.xと同等であり、_ENV自体はローカル変数であり、環境と呼ばれる任意のテーブルです。
Luaがグローバル変数を処理する方法:
すべてのコードをコンパイルする前に、外層にローカル変数_ENVを作成します。
すべてのフリーネームvarは_ENV.varに変換されます。
関数loadは、グローバル環境を使用して、コードセグメントの最初のアップ値を初期化します。これは、lua構文によって内部的に維持されるテーブルです。
- _ENVを使用する
コードセグメント(ファイル)には_ENV変数があります。_ENV = nilは、後続のコードがグローバル変数に直接アクセスするのを防ぎます。_ENVの主な目的は、コードセグメントが使用される環境を変更することです。次のように、継承を使用して古い環境をロードします。
local newgt = {}
setmetatable(newgt, {__index = _G})
_ENV = newget
割り当てはすべて新しいテーブルで行われます。グローバル変数の変数を変更するために使用できるのは_Gのみです。
- 環境とモジュール
_ENVは、グローバル変数の汚染を解決します。
- _EVNとロード
Loadは通常、ロードされたコードセグメントの値_ENVをグローバル環境に初期化します。また、_ENVに別の初期値を指定するためのオプションのパラメーターがあります。
env = {}
loadfile("config.lua","t",env)()
サンドボックスでの実行に似ています。
コードを数回実行します。そのたびに異なる環境で、2つのオプションは次のとおりです。
最初のものはdebug.setupvalue(f、1、env)を使用します
最初のパラメーターは指定された関数、2番目のパラメーターはアップ値インデックス(常に1)、3番目のパラメーターは新しいアップ値です。[デバッグライブラリによっては、可視性ルールを破る]
もう1つは、次のように、ロードされるたびにコードセグメントを変更することです。
lua把所有代码段当做可变长参数函数进行编译,多出来这一行会把传给代码段的第一个参数赋值给_ENV,从而改变环境。
prefix = "_ENV = ...;"
f = loadwithprefix(prefix,io.lines(filename,"*L"))
...
env1 = {}
f(env1)
env2 = {}
f(env2)