概要
JavaScript でのスコープとコンテキストの実装は、JavaScript 言語独自の機能です。ある程度、JavaScript 言語は非常に柔軟です。 Javascript の関数はさまざまなコンテキストを取ることができ、スコープはカプセル化して保存できます。まさにこのような特性があるからこそ、JavaScript には便利なデザイン パターンが数多く提供されています。ただし、スコープとコンテキストは、JavaScript プログラマーが開発中によく混乱する領域でもあります。
以下では、JavaScript におけるスコープとコンテキストの概念とそれらの違いを紹介します。
スコープ VS コンテキスト
最初に注意すべき重要なことは、スコープとコンテキストは同じ概念ではなく、同じものを指すわけではないということです。フロントエンドのオタクとして、これら 2 つの概念が混同されている記事をよく見かけます。その結果、読めば読むほど不明瞭になることがあります。これら 2 つの概念は長い間混同されていたようです。そこで、多くの情報を確認し、これら 2 つの概念について簡単に説明しました。 :stuck_out_tongue_closed_eyes:
JavaScript では、関数が呼び出されるときに、その関数にバインドされたスコープとコンテキストが存在します。基本的に、スコープは関数ベースであり、コンテキストはオブジェクトベースです。つまり、スコープは、関数が呼び出されたときに関数内の変数へのアクセスに適用されます。コンテキストは通常、「this」キーワードの値を指します。これは、現在実行中のコードを所有するオブジェクトへの参照です。
変数スコープ
変数はローカルまたはグローバル スコープで定義でき、それぞれローカル変数およびグローバル変数と呼ばれます。グローバル変数は、関数の外で宣言された変数を指し、プログラム内のどこからでもアクセスできます。ローカル変数は、関数本体内で定義された変数を指します。ローカル変数は、関数本体またはネストされた関数内でのみアクセスでき、関数の外部からはアクセスできません。
Javascript は現在、ブロックレベルのスコープ (if、switch、for などのステートメントで定義された変数) をサポートしていません。これは、ブロック内で定義された変数にはブロックの外からもアクセスできることを意味します。ただし、ES6 では、「let」キーワードを使用してブロックレベルのスコープを定義できます。
スコープの内容については、他の情報を確認してください。この部分の内容は比較的簡単です。
「この」コンテキスト
コンテキストは通常、関数の呼び出し方法によって異なります。関数がオブジェクトのメソッドとして呼び出される場合、「this」は関数が呼び出されたオブジェクトを指します。
JavaScript はシングルスレッド言語です。つまり、JavaScript がブラウザーで実行されているとき、一度に実行できる処理は 1 つだけであり、他の処理はメソッド内のキューに入れられて処理を待機します。
1. JavaScript コード ファイルがブラウザーに読み込まれると、デフォルトでは最新のエントリがグローバル実行コンテキストになります。関数がグローバル コンテキストで呼び出されると、プログラムは呼び出された関数に入り、JavaScript エンジンはその関数の新しい実行コンテキストを作成し、それを実行コンテキスト スタックの先頭にプッシュします。ブラウザは常に、現在スタックの最上位にあるコンテキストを実行します。実行が完了すると、コンテキストはスタックの最上位からポップされ、その下のコンテキストでコードが実行されます。このようにして、スタック内のコンテキストは順番に実行され、グローバル コンテキストに戻るまでスタックからポップされます。
2. 実行コンテキストは、作成フェーズと実行フェーズの 2 つのフェーズに分けることができます。作成フェーズでは、JavaScript インタープリターはまず変数オブジェクト (「アクティベーション オブジェクト」とも呼ばれます) を作成します。アクティブ オブジェクトは、変数、関数宣言、およびパラメーターで構成されます。この段階で、関数のスコープ チェーンが初期化され、これによって参照されるオブジェクトも決定されます。次に実行フェーズが始まり、コードが解釈されて実行されます。
Javascript コードでは、関数コンテキストはいくつでも存在できます。関数が呼び出されるとき、JavaScript インタプリタは新しいコンテキストとプライベート スコープを作成し、関数内で宣言された変数には外部から直接アクセスできないことはすでにわかっています。現在の関数のスコープ。
3. 上記の説明を通じて、関数の「実行コンテキスト」の基本的な概念がわかりましたが、これは誰もが最も混乱する場所でもあります。 JavaScript の「実行コンテキスト」は主にスコープを指し、上記の 4 番目のセクションで言及した「このコンテキスト」ではありません。 Javascript には同様の紛らわしい概念がたくさんありますが、それぞれの概念が指す特定のオブジェクトを理解していれば、もう混乱することはありません。したがって、誰もが「実行コンテキスト」と「このコンテキスト」を正確に区別できるようになることを願っています。 」。
厳密ではないかもしれませんが、簡単に言うと、実行コンテキストはスコープに関連する概念です。
スコープチェーン
実行コンテキストごとに、それにバインドされたスコープがあります。スコープ チェーンには、実行コンテキスト スタック内の実行コンテキスト アクティベーション オブジェクト (少し複雑に聞こえます) が含まれています。スコープ チェーンは、変数へのアクセスと識別子の解決を決定します。
コード例:
上記のコードを実行すると、ネストされた関数が実行されます。上記のコードに関する限り、スコープ チェーンも上から下に 4 番目、3 番目、2 番目、1 番目、グローバルの順序で形成されます。関数 4 は、グローバル スコープ内の変数にアクセスでき、関数 3、2、および 1 で定義された変数にアクセスできます。
注意すべき点の 1 つは、関数本体内では、ローカル変数は同じ名前のグローバル変数よりも優先されるということです。関数内で宣言されたローカル変数、または関数のパラメータに含まれる変数がグローバル変数と同じ名前である場合、グローバル変数はローカル変数によって上書きされます。
簡単に言うと、変数にアクセスしようとするたびに、プログラムは現在の関数のスコープ内で変数を検索します。変数が見つからない場合は、関数の上位レベルまでスコープ チェーンに沿って検索します。変数が見つからない場合は、unknown を返します。
概要
この記事では、JavaScript のコンテキストとスコープの関連概念を紹介します。また、JavaScript には、クロージャなどのさらに重要な概念がいくつかあります。将来、これらを理解できれば、記事を書くことになります~~