JavaScriptスコープのスコープの探索(一)
1971 ワード
スコープは何ですか?
作用領域は、変数を格納するための設計がよく、これらの変数にアクセスしやすい規則に相当する.作用域は決定した周期によって静的作用域と動的作用域に分けられる.JavaScriptにはダイナミックスコープが存在しないので、ここでは議論しません.静的作用域はまた語法作用域と呼ばれ、語法作用域を用いた変数を語法変数と呼び、語法変数はコンパイル時にその作用領域を決定します.
変数の割り当て
作用領域を理解するために、JavaScriptにおける変数の割り当て操作を分析します.
LHSとRHSの割り当てを区別する.
変数が賦値操作の左側に現れたら、LHSクエリを行い、右側に現れたらRHSクエリを行います.詳細には、RHSは現在の変数の格納値を見つけるためだけであり、LHSは現在の変数の位置を見つけ、対応する値を付与するためである.したがって、RHSクエリーは必ずしも等号の右側に発生するとは限らない.
なぜLHSとRHSを区別することが重要ですか?
変数がまだ宣言されていない場合、二つのクエリの挙動は異なるからです.
スコープのネスト
一つのブロックまたは関数が他のブロックまたは関数にネストされると、スコープのネストが発生します.JavaScriptでは、スコープに対する処理が特別であり、現在のスコープで変数が見つからない場合、エンジンは外層ネストのスコープ内で検索を続けます.この変数が見つかったら、または最外層作用領域(グローバルスコープ)に到達するまで検索します.
スコープ検索は、最初の一致する変数識別子を見つけると停止します.多層のネストされた作用領域において、同名の識別子が存在すると、内部の識別子は外部の識別子を「遮蔽」する.グローバルスコープで定義されている変数は、自動的にグローバルオブジェクトの属性となりますので、グローバルオブジェクト属性の参照によってアクセスできますが、グローバルでない変数は遮蔽されていると、どうしてもアクセスできません.
作用領域は、変数を格納するための設計がよく、これらの変数にアクセスしやすい規則に相当する.作用域は決定した周期によって静的作用域と動的作用域に分けられる.JavaScriptにはダイナミックスコープが存在しないので、ここでは議論しません.静的作用域はまた語法作用域と呼ばれ、語法作用域を用いた変数を語法変数と呼び、語法変数はコンパイル時にその作用領域を決定します.
変数の割り当て
作用領域を理解するために、JavaScriptにおける変数の割り当て操作を分析します.
var a = 2;
この割当文を見ると、私たちは声明として認識することができますが、実はこの文は二つの異なる動作を実行しています.まず、コンパイラはこの作用領域に現在の変数が存在するかどうかを尋ねます.もしあるなら、その宣言を無視します.さもなければ、音声変数aを無視します.そして、運転時にエンジンがそのスコープで変数を検索し、変数aに2を割り当てます.LHSとRHSの割り当てを区別する.
変数が賦値操作の左側に現れたら、LHSクエリを行い、右側に現れたらRHSクエリを行います.詳細には、RHSは現在の変数の格納値を見つけるためだけであり、LHSは現在の変数の位置を見つけ、対応する値を付与するためである.したがって、RHSクエリーは必ずしも等号の右側に発生するとは限らない.
console.log(a); // a RHS
a = 2; // a LHS
関数を呼び出すと、割り当て操作がより複雑になります.function foo(a) {
console.log(a);
}
foo(1);.
この例はまず、fooという関数名をRHSクエリし、括弧内で暗黙的なLHS呼び出し、つまりa=1の割当動作を行い、最後にconsolie.log(a)でaをRHSクエリした.なぜLHSとRHSを区別することが重要ですか?
変数がまだ宣言されていない場合、二つのクエリの挙動は異なるからです.
function foo() {
console.log(a + b)
}
var a = 5;
foo();
上記の関数では、Bに対してRHSクエリを実行していますが、この変数は見つけられません.つまり変数bは宣言されていません.エンジンはReferenceErrror異常を投げます.LHSクエリを行っている時に、上記の例のvar a=5のように.この変数が見つからない場合、グローバルスコープでその名前の変数(非厳格モード)が作成されます.ES 5は厳密モードを導入しています.通常モードに比べて、厳密モードでは自動的または暗黙的にグローバル変数を作成することが禁止されていますので、厳密モードではLHSクエリが失敗した場合はグローバルスコープで作成され、グローバル変数に戻ることはありません.ReferenceErrer異常を返します.また、RHSクエリーを行う場合、この変数名が存在するが、実行操作は変数タイプに合わない.例えば、関数タイプではない値を関数呼出ししたり、nullまたはundefinedタイプの値のうちの属性を引用したりすると、エンジンは別のタイプの異常を投げ出します.スコープのネスト
一つのブロックまたは関数が他のブロックまたは関数にネストされると、スコープのネストが発生します.JavaScriptでは、スコープに対する処理が特別であり、現在のスコープで変数が見つからない場合、エンジンは外層ネストのスコープ内で検索を続けます.この変数が見つかったら、または最外層作用領域(グローバルスコープ)に到達するまで検索します.
function foo(a) {
console.log(a + b);
}
var b = 2;
foo(1); // 3
マスク効果スコープ検索は、最初の一致する変数識別子を見つけると停止します.多層のネストされた作用領域において、同名の識別子が存在すると、内部の識別子は外部の識別子を「遮蔽」する.グローバルスコープで定義されている変数は、自動的にグローバルオブジェクトの属性となりますので、グローバルオブジェクト属性の参照によってアクセスできますが、グローバルでない変数は遮蔽されていると、どうしてもアクセスできません.