変数の範囲については、C、Javaなどの言語は「ブロックスコープ」メソッドを採用しています。対照的に、JavaScriptは「関数範囲」メソッドを採用します - 変数の範囲は、それが位置する関数によってのみ決定され、そのような論理ブロックとは何の関係もありません。たとえば、次の例は、CやJavaなどの言語とは異なるJavaScriptの動作を示しています。
コードコピーは次のとおりです。
関数(){
var s = 42; // sは関数全体に見えます
if(s> 3){
var x = "test"; // xは関数全体に見えます
for(var i = 0; i <10; i ++){
console.log(i);
}
console.log(i); //関数全体に表示されます
}
console.log(i);
console.log(x);
}
CやJavaなどの「ブロックスコープ」言語では、ステートメントやステートメントが完了した場合などの論理ブロックの後、これらの論理ブロック内で定義された変数が破壊されます。 JavaScriptは異なります。変数が関数内で定義されている限り、関数全体のすべてのコードは、変数定義の前にある場合でも、変数にアクセスできます。
コードコピーは次のとおりです。
関数(){
console.log(a); //未定義
var a = "test";
console.log(a); //テスト
}
上記の例では、aが関数で定義されていない場合、console.log(a)はリファレンスエラーをスローします。 Aが関数で定義される場合、この定義が変数呼び出しステートメントの後であっても、aへの呼び出しは法的操作です(変数の定義がコールステートメントの後に発生する場合、コールステートメントの変数の値は未定義です)。実際、関数のVARキーワードで定義されたすべての変数は、関数の開始(割り当て操作がVARによって定義されたラインに残ります)に引き上げられ、JavaScriptでホイストと呼ばれます。たとえば、上記のコードは以下と同等です。
コードコピーは次のとおりです。
関数(){
var a;
console.log(a); //未定義
a = "test";
console.log(a); //テスト
}
変数の範囲チェーン
JavaScriptの変数のストレージに連絡すると、JSで「関数範囲」と巻き上げを十分に理解することができます。変数はグローバルオブジェクトまたは関数コールオブジェクトに保存されるため、関数内の変数を定義するとき、変数が関数呼び出しで定義されていても、この変数と同じ名前のプロパティがこの関数呼び出しで使用される関数呼び出しオブジェクトに必然的に表示されます。これにより、変数に関数のどこにでもアクセスできます。
関数呼び出しに関しては、JavaScriptにはもう1つのより興味深い概念があります。変数のスコープチェーン - 変数はグローバルオブジェクトまたは関数コールオブジェクトに保存されているため、変数にアクセスするときに複数のオブジェクトから値を取得できます。次のコードは例です。
コードコピーは次のとおりです。
var x = "test";
関数(){
//レベル1関数
var x = "temp";
関数(){
//レベル2関数
var x = "real";
//ここからXにアクセスしてみてください。 xは「本物」になります。
}
}
上記のコードのレベル2関数内で、X変数にアクセスしようとすると、プログラムは3つのオブジェクトから対応する属性値を検索できます。レベル2関数を呼び出すために使用される関数呼び出しオブジェクト、レベル1関数を呼び出すために使用される関数呼び出しオブジェクト、および関数によって定義されたネストされた関係に従って、JavaScriptはグローバルオブジェクトと機能オブジェクトを構成するオブジェクトを生成します。変数にアクセスすると、プログラムはアクセスステートメントに最も近いオブジェクトから検索を開始します。検索が見つからない場合、グローバルオブジェクトまでオブジェクトチェーンの前のレベルでオブジェクトでオブジェクトで検索し続けます。
このオブジェクトチェーンは変数の範囲に関連しているため、「スコープチェーン」とも呼ばれます。
スコープチェーンを一時的に変更し、スコープチェーンのフロントエンドにオブジェクトを挿入する必要がある場合(最初にアクセスする関数オブジェクトとして)、withステートメントを使用できます。
コードコピーは次のとおりです。
(o)で{
//コードオブジェクトのプロパティを使用しますo。
}
ただし、JavaScript Strictモードでは、ステートメントが無効になっています。非ストライクモードであっても、ステートメントが推奨されません。