スコープは JavaScript の最も重要な概念の 1 つです。JavaScript をよく学びたい場合は、JavaScript のスコープとスコープ チェーンの動作原理を理解する必要があります。今日の記事では、JavaScript のスコープとスコープ チェーンについて簡単に紹介し、誰もが JavaScript をより良く学習できるようにしたいと考えています。
JavaScript スコープ
どのプログラミング言語にもスコープの概念があります。簡単に言えば、スコープは変数と関数のアクセス可能な範囲です。つまり、スコープは変数と関数の可視性とライフサイクルを制御します。 JavaScript には、グローバル スコープとローカル スコープの 2 種類の変数スコープがあります。
1. グローバル スコープ
コード内のどこからでもアクセスできるオブジェクトにはグローバル スコープがあります。一般に、グローバル スコープを持つ状況がいくつかあります。
(1) 最も外側の関数とその外側で定義された変数はグローバル スコープを持ちます。例:2. ローカルスコープ
グローバル スコープとは対照的に、ローカル スコープは通常、固定されたコード フラグメント内でのみアクセスできます。最も一般的なものは関数内にあるため、場所によっては、このスコープを関数スコープと呼んでいる場合があります。次のコードの、blogName および関数 innerSay はローカル スコープのみを持ちます。
コードをコピー
コードは次のとおりです:
値は、関数内に出現する順序でランタイム コンテキストのスコープ チェーンにコピーされます。これらは一緒に「アクティベーション オブジェクト」と呼ばれる新しいオブジェクトを形成します。このオブジェクトには、すべてのローカル変数、名前付きパラメータ、パラメータ コレクションが含まれており、実行時にこのオブジェクトがスコープ チェーンのフロント エンドにプッシュされます。コンテキストが破棄されると、アクティブなオブジェクトも破棄されます。新しいスコープ チェーンは次のとおりです:
関数の実行中に変数が見つからない場合、識別子の解析プロセスを経て、データを取得して保存する場所が決定されます。このプロセスはスコープ チェーンの先頭、つまりアクティブなオブジェクトから開始され、同じ名前の識別子が見つかった場合は、その識別子に対応する変数を使用します。見つからない場合は、続行します。スコープチェーン内の次のオブジェクトを検索します。 If 検索後にオブジェクトが見つからない場合、識別子は未定義とみなされます。関数実行時には、各識別子に対してこのような検索処理が行われます。
スコープチェーンとコードの最適化
スコープ チェーンの構造から、識別子がランタイム コンテキストのスコープ チェーンの深いところにあるほど、読み取りと書き込みの速度が遅くなることがわかります。上の図に示すように、グローバル変数は常にランタイム コンテキスト スコープ チェーンの最後に存在するため、識別子の解決中にグローバル変数を見つけるのが最も遅くなります。したがって、コードを記述するときは、グローバル変数の使用をできるだけ少なくし、ローカル変数をできるだけ使用する必要があります。経験則としては、クロススコープ オブジェクトが複数回参照される場合は、使用する前にローカル変数に格納します。たとえば、次のコード:
document.getElementById("btnChange").onclick=function(){
document.getElementById("targetCanvas").style.backgroundColor="red";
};
}
var doc=ドキュメント
doc.getElementById("btnChange").onclick=function(){
doc.getElementById("targetCanvas").style.backgroundColor="red";
};
}
スコープチェーンの変更
対応するランタイム コンテキストは関数が実行されるたびに一意であるため、同じ関数を複数回呼び出すと、関数の実行が完了すると複数のランタイム コンテキストが作成されます。各ランタイム コンテキストはスコープ チェーンに関連付けられます。通常、ランタイム コンテキストの実行中、そのスコープ チェーンは with ステートメントと catch ステートメントによってのみ影響を受けます。
with ステートメントは、オブジェクトを使用してコードを繰り返し記述することを避けるためのショートカット方法です。例:
with(ドキュメント){
var bd=body,
links=getElementsByTagName("a"),
i=0、
len=リンクの長さ
while(i 更新(リンク[i ]);
コードが with ステートメントまで実行されると、ランタイム コンテキストのスコープ チェーンが一時的に変更されます。パラメーターで指定されたオブジェクトのすべてのプロパティを含む新しい可変オブジェクトが作成されます。このオブジェクトはスコープ チェーンの先頭にプッシュされます。つまり、関数のすべてのローカル変数が 2 番目のスコープ チェーン オブジェクト内にあるため、アクセスコストが高くなります。以下に示すように: したがって、この例では、ドキュメントをローカル変数に保存するだけでパフォーマンスが向上するため、プログラム内で with ステートメントを使用することは避けてください。 スコープ チェーンを変更するもう 1 つの点は、try-catch ステートメント内の catch ステートメントです。 try コード ブロックでエラーが発生すると、実行プロセスは catch ステートメントにジャンプし、その後、例外オブジェクトが可変オブジェクトにプッシュされ、スコープの先頭に配置されます。 catch ブロック内では、関数のすべてのローカル変数が 2 番目のスコープ チェーン オブジェクトに配置されます。サンプルコード: doSomething() }キャッチ(例){ alert(ex.message); // ここでスコープチェーンが変更されます } doSomething() }キャッチ(例){ handleError(ex); //プロセッサメソッドに委任します }
ここで width ステートメントは、ドキュメントを複数回記述することを避けるために使用されており、効率的であるように見えますが、実際にはパフォーマンスの問題が発生します。
try{
catch ステートメントが実行されると、スコープ チェーンは以前の状態に戻ることに注意してください。 try-catch ステートメントはコードのデバッグや例外処理に非常に役立つため、完全に回避することはお勧めできません。コードを最適化することで、catch ステートメントのパフォーマンスへの影響を軽減できます。良いパターンは、エラー処理を関数に委任することです。例:
試してください{
最適化されたコードでは、catch 句で実行されるコードは handleError メソッドだけです。この関数は例外オブジェクトをパラメータとして受け取るため、エラーをより柔軟かつ均一に処理できます。実行されるステートメントは 1 つだけであり、ローカル変数にはアクセスされないため、スコープ チェーンの一時的な変更はコードのパフォーマンスに影響しません。