関連書籍: JavaScript プロトタイプとクロージャ シリーズについての私の理解を語る (Shuishhou Note 6)
範囲
「JavaScript 言語の本質とプログラミングの実践」からスコープの定義を引用:
変数スコープは、変数の可視性とも呼ばれます。可変スコープにより情報の隠蔽が完了し、「断片化」の問題が解決されます。
js にはブロック レベルのスコープはありません (ES6 には let があり、これは {}、if、for で宣言でき、スコープはブロック レベルに制限されます。変数の変数プロモーションはありません) let で宣言しました!ここでは話しません。これは、たまたま見たからです)。
コードを書くときは、曖昧さを避けるために「ブロック」内で変数を宣言すべきではありません。
for(var i = 0; i < 10; i++) { //不好的声明方式
//...
}
console.log(i);
/*----------------------------------------------*/
var i = 0; //好的声明方式
for(i = 0; i < 10; i++) {
//....
}
console.log(i);
グローバル スコープに加えて、JavaScript には関数スコープもあります。
変数を宣言する場合、グローバル コードはフロントエンドで宣言され、関数内で宣言された変数は関数本体の前で宣言する必要があります。同時に、変数を宣言するときは「var」演算子を使用する必要があります。
var a = 10, //全局作用域
b = 20;
function fn() { //fn函数作用域
var a = 100,
c = 300;
function bar() { //bar函数作用域
var a = 1000,
d = 4000;
}
}
グローバル コード、fn 関数、bar 関数はすべてスコープを形成します。スコープには上位と下位の関係があり、その上位と下位の関係は関数が作成されるスコープによって異なります。 bar 関数は、fn 関数スコープの下に作成されます。「fn 関数スコープ」は、「bar 関数スコープ」の上位にあります。
スコープの最大の用途は、異なるスコープ内の同じ名前の変数が競合しないようにすることです。
----------------------------------------------- --- ----------------------------------
スコープは、関数が呼び出されたときではなく、関数が定義されたときに決定されます。
1. グローバル コンテキスト環境はプログラムのロード時に決定され、プログラムの実行時に変数に値が割り当てられます。
2. 36 行目まで実行し、fn(10) を呼び出し、fn 関数の実行コンテキストを作成し、スタックをプッシュし、このコンテキストをアクティブ状態に設定します。
3. 32 行目まで実行し、bar(100) を呼び出し、bar(100) 関数の実行コンテキストを作成し、スタックをプッシュし、このコンテキストをアクティブ状態に設定します。
4. bar(100) が呼び出された後、スタックからポップされ、bar(100) 関数コンテキストが破棄されます。次に、行 33 を実行して、bar(200) を呼び出し、bar(200) 関数の実行コンテキストを作成し、スタックをプッシュし、このコンテキストをアクティブ状態に設定します。
5. bar(200) への呼び出しが完了すると、それはスタックからポップされ、そのコンテキストは破棄されます。制御は fn(10) コンテキストに渡され、再びアクティブになります。
6. このとき、fn(10) が呼び出され、スタックからポップされ、そのコンテキストが破棄されます。制御はグローバル実行コンテキストに移されます。
このコード部分の実行プロセスはこの時点で完了しています。
次に、元の著者から全体像を借用します:
概要:
スコープは単なる「芝生」であり、変数の値はスコープに対応する実行コンテキストを通じて取得する必要があります。同じスコープ内では、異なる呼び出しによって異なる実行コンテキストが生成され、したがって異なる変数値が生成されます。したがって、スコープ内の変数の値は実行中に決定されますが、スコープは関数の作成時に決定されます。したがって、スコープ内の変数の値を見つけたい場合は、このスコープに対応する実行コンテキストを見つけて、その中で変数の値を見つける必要があります。