スコープ JavaScript 変数のスコープは関数ごとに分けられており、その特徴を簡単に理解できるように、例を使って説明します。
例 1:
<script type="text/javascript"> var i = 1; // 弹出内容为 1 true 的提示框 alert(window.i + ' ' + (window.i == i)); </script>
分析:
グローバルに定義された変数は、実際にはウィンドウ オブジェクトの属性です。
上記の例からわかるように、グローバル変数を定義すると、ウィンドウ オブジェクトが対応する属性を生成します。コードでこの属性が生成されないようにする方法は次のとおりです。
例 2:
<script type="text/javascript"> var document = 1; window.onload = function(){ alert(document); } // 弹出内容为 1 的提示框 alert(window.document); </script>
これは見たくない状況ですが、次のようにすることができます。
<script type="text/javascript"> function test(){ var document = 1; window.onload = function(){ alert(document); } } test(); // 弹出内容为 [object] 的提示框 alert(window.document); </script>
コードをより簡潔にするために、次のようにします。
<script type="text/javascript"> (function(){ var document = 1; window.onload = function(){ alert(document); } })(); // 弹出内容为 [object] 的提示框 alert(window.document); </script>
分析:
この形式の匿名メソッドの実行は、主流の JavaScript フレームワークでよく見られます。これにより、ウィンドウ オブジェクトの不要な属性の生成を回避し、競合の可能性を減らすことができます。
例 3:
<script type="text/javascript"> (function(){ if('1' == '1'){ var i = 1; } // 弹出内容为 1 的提示框 alert(i); })(); </script>
分析:
変数のスコープは、{} ブロックではなく関数全体です。
例 4:
<script type="text/javascript"> var i = 1; // 弹出内容为 1 的提示框 alert(i); var i = 2; // 弹出内容为 2 的提示框 alert(i); </script>
分析:
変数は再定義できますが、これは他の多くの言語では機能しないため、少し奇妙に思えます。
例 5:
<script type="text/javascript"> function test(){ i = 1; } test(); // 弹出内容为 1 的提示框 alert(window.i); </script>
分析:
初期化されていない変数に値が割り当てられている場合、この変数はグローバル変数として使用されます。
例 6:
<script type="text/javascript"> window.onload = function(){ var i = 1; function test(){ alert(i); } // 弹出内容为 1 的提示框 test(); } </script>
分析:
内部関数は外部関数の変数にアクセスでき、これはクロージャという新しい概念につながります。
クロージャ
クロージャとは何ですか? 簡単に言うと、関数 A が終了しても、その内部関数 B が A で定義された変数にアクセスできる関数です。例を通してそれについて学びましょう。
例 7:
<script type="text/javascript"> window.onload = function(){ var i = 1; window.onunload = function(){ alert(i); } } </script>
分析:
ページ全体が読み込まれると、onload イベントがトリガーされます。この onload イベント メソッドは、ウィンドウの onunload イベントのメソッドを登録します。このメソッド onload イベント メソッドで宣言された変数が使用され、onload イベント メソッドが終了します。この時点で、クリックしてウィンドウを閉じると、onunload イベントが発生したことを示す内容が 1 のプロンプト ボックスが表示されます。メソッドは、onload イベント メソッドで宣言された変数を正常に呼び出しました。
クロージャの特性をさらに理解するために、次の例を見てください
例 8:
<script type="text/javascript"> function initX(oarg){ // 定义一个变量 var x = oarg; // 定义一个显示变量的方法 var funGet = function(){ alert(x); } // 定义一个对变量进行修改的方法 var funSet = function(iarg){ x = iarg; } // 返回这两个方法 return [funGet,funSet]; } // 运行一个方法实例,返回值为包含 get 和 set 方法的数组 var funArr = initX(1); // 得到 get 方法 var funGet = funArr[0]; // 得到 set 方法 var funSet = funArr[1]; // 运行 get 方法,显示initX方法实例内的 x 变量,结果为 1 funGet(); // 运行 set 方法,对initX方法实例内的 x 变量进行赋值 funSet(2); // 运行 get 方法,显示initX方法实例内的 x 变量,结果为 2 funGet(); </script>
分析:
内部関数が外部関数で定義された変数を呼び出すとき実際、参照はこの変数のメモリ ブロックに対するものであるため、内部関数を呼び出すと、参照される変数の値は現在の変数の実際の内容になります。
クロージャ機能は強力ですが、注意しないとトラブルを引き起こす可能性もあります。以下の例を参照してください。
例 9:
<button id="main">run</button> <script type="text/javascript"> (function(){ var obj = document.getElementById("main"); var funArr = ['onclick','onkeypress']; for(var i=0; i<funArr.length; i++){ var temp = funArr[i]; obj[temp] = function(){ alert(temp); } } })(); </script>
コードを記述する本来の目的は、ID が main であるボタンのクリック イベントとキー イベントを登録することであり、イベントの内容はプロンプト ボックスをポップアップすることです。それぞれイベント名が入ります。しかし、結果は少し奇妙です。2 つのイベントのプロンプト ボックスはすべて onkeypress です。注意深く分析すると、2 つのイベント メソッドが呼び出されたときに temp 変数がコンテンツを指していることがわかります。この問題を解決するには、次の方法を変更できます:
<button id="main">run</button> <script type="text/javascript"> (function(){ var obj = document.getElementById("main"); var funArr = ['onclick','onkeypress']; for(var i=0; i<funArr.length; i++){ (function(){ var temp = funArr[i]; obj[temp] = function(){ alert(temp); } })(); } })(); </script>
各ループが関数インスタンスを生成し、関数インスタンスが生成されるように、for ループ内のコードを関数に配置します。 funArr 配列の各値を記録することで、上記で発生した問題を回避できます。