ホームページ >ウェブフロントエンド >jsチュートリアル >JavaScript 変数のスコープと Closure_JavaScript スキル

JavaScript 変数のスコープと Closure_JavaScript スキル

PHP中文网
PHP中文网オリジナル
2016-05-16 18:48:311067ブラウズ

スコープ JavaScript 変数のスコープは関数ごとに分けられており、その特徴を簡単に理解できるように、例を使って説明します。

例 1:

<script type="text/javascript"> 
var i = 1; 
// 弹出内容为 1 true 的提示框 
alert(window.i + &#39; &#39; + (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(&#39;1&#39; == &#39;1&#39;){ 
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 = [&#39;onclick&#39;,&#39;onkeypress&#39;]; 
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 = [&#39;onclick&#39;,&#39;onkeypress&#39;]; 
for(var i=0; i<funArr.length; i++){ 
(function(){ 
var temp = funArr[i]; 
obj[temp] = function(){ 
alert(temp); 
} 
})(); 
} 
})(); 
</script>

各ループが関数インスタンスを生成し、関数インスタンスが生成されるように、for ループ内のコードを関数に配置します。 funArr 配列の各値を記録することで、上記で発生した問題を回避できます。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。