前の言葉
ほとんどの場合、スコープについて混乱している主な理由は、機能位置のネストされた順序で変数検索を実行するか、関数呼び出しの順序で実行すべきかを区別できないことです。このメカニズムの干渉と相まって、可変検索は非常にエラーになりやすいです。これは、実際には2つのスコープ作業モデルによって引き起こされます。スコープは、語彙範囲と動的範囲に分割されます。これらの2つのスコープモデルを区別することにより、変数検索プロセスを明確に理解できます。この記事は、JavaScriptスコープシリーズの第2章です - 語彙範囲と動的範囲
語彙範囲
最初の記事で述べたように、コンパイラの最初の作業段階はWord分詞と呼ばれ、文字列で構成される文字列を語彙単位に分解します。この概念は、語彙範囲を理解するための基礎です
簡単に言えば、語彙範囲は語彙段階でスコープを定義します。これは、コードを書くときに変数とブロックスコープが記述される場所によって決定されます。したがって、語彙アナライザーがコードを処理する場合、スコープは変更されません。
関係
関数がどこに呼ばれていても、どのように呼び出されても、その語彙スコープは、関数が宣言されている位置によってのみ決定されます。
function foo(a){var b = a * 2; function bar(c){console.log(a、b、c);} bar(b * 3);} foo(2); // 2 4 12この例では、3つのネストされたスコープがあります。理解するために、それらを段階的に含まれるいくつかの泡と考えてください
スコープバブルは、対応するスコープブロックコードが書かれている場所によって決定され、段階的に含まれています。
バブル1には、識別子が1つだけのグローバルスコープ全体が含まれています:foo
バブル2には、FOOによって作成されたスコープが含まれています。
Bubble 3には、Barによって作成されたスコープが含まれており、識別子は1つだけです。
探す
スコープされた泡の構造とその位置関係は、エンジンに十分な位置情報を提供し、エンジンが識別子の位置を見つけるために使用します。
コードスニペットでは、エンジンはconsole.log(...)宣言を実行し、3つの変数a、b、cへの参照を探します。最初に、最も内側の範囲、つまりバー(...)関数の範囲から始まります。エンジンはここを見つけることができないため、ネストされたfoo(...)の範囲で検索を続けるために前のレベルに移動します。 Aはここにあるため、エンジンはこのリファレンスを使用します。 bにも同じことが言えます。そしてCのために、エンジンはそれをバーで見つけました(...)
[注]語彙スコープ検索では、第1レベルの識別子のみを探します。コードがfoo.bar.bazを参照する場合、語彙スコープ検索はFOO識別子のみを見つけようとします。この変数を見つけた後、オブジェクト属性アクセスルールはそれぞれbarとbaz属性へのアクセスを引き継ぎます
foo = {bar:{baz:1}}; console.log(foo.bar.baz); // 1カバー
スコープ検索は、ランタイムが配置されている最も内側のスコープから始まり、最初のマッチング識別子が満たされるまで、ステップまたは上向きに進みます。
同じ名前の識別子は、「閉塞効果」と呼ばれる多層ネストされたスコープで定義できます。内部識別子は、外部識別子を「オクルード」します
var a = 0; function test(){var a = 1; console.log(a); // 1} test();グローバル変数はグローバルオブジェクトの自動的に属性であるため、グローバルオブジェクトの語彙名を直接通過するのではなく、グローバルオブジェクトの属性を参照することで直接アクセスできます。
var a = 0; function test(){var a = 1; console.log(window.a); // 0} test();この手法により、同じ名前の変数によって不明瞭なグローバル変数へのアクセスが可能になります。しかし、非グローバル変数がブロックされている場合、何があってもアクセスできません。
動的範囲
JavaScriptは語彙スコープを使用しており、その最も重要な機能は、その定義プロセスがコードの執筆段階で行われることです。
では、なぜ動的範囲を導入するのですか?実際、動的範囲は、これをいとこするためのJavaScriptのもう1つの重要なメカニズムです。範囲の混乱のほとんどは、語彙範囲とこのメカニズムが混乱しているためです。
動的なスコープは、機能とスコープがどこでも宣言され、宣言される方法を気にしません。言い換えれば、スコープチェーンはコードにネストするスコープではなく、コールスタックに基づいています
var a = 2; function foo(){console.log(a);} function bar(){var a = 3; foo();} bar();[1]語彙範囲にある場合、それは現在のJavaScript環境です。変数Aは最初にFOO()関数で検索されますが、見つかりません。スコープチェーンに従ってグローバルスコープで検索し、2の値を見つけて割り当てます。したがって、コンソール出力2は2
【2】同様に、動的範囲にある場合、変数Aは最初にFOO()で検索され、見つかりません。ここでは、foo()関数が呼び出される場所、つまりbar()関数を検索するために、コールスタックに従って、値を3に見つけて割り当てます。したがって、コンソールは出力3になります。
概要:2つのスコープの違い。要するに、語彙スコープは定義時に決定され、動的範囲は実行時に決定されます。
上記は、編集者が紹介した語彙範囲と動的範囲の第2部です。それがあなたに役立つことを願っています。もっと知りたい場合は、wulin.comに注意してください!