1. JavaScript のスコープ
JavaScript 変数には実際には、グローバル変数と関数の内部変数の 2 つのスコープしかありません。関数内の任意の場所で定義された変数のスコープ (var スコープ) は、関数本体全体です。
グローバル変数: ウィンドウ オブジェクトの下のオブジェクト プロパティを参照します。
スコープの分割: コンテキストに基づいて、ブロックではなく機能によって分割されます。
2 つの点を強調します:
1. JavaScript では同じスコープ内で変数を繰り返し定義でき、後の定義で前の定義が上書きされます。
2. 関数内にキーワード var を追加せずに変数を定義すると、デフォルトでグローバル変数になります。
var scope="global"; function t(){ console.log(scope); //"global" scope="local" console.log(scope); //"local" } t(); console.log(scope); //"local" var scope="global"; function t(){ console.log(scope); //"undefined" var scope="local" console.log(scope); //"local" } t(); console.log(scope); //"global"
変数解決のプロセスでは、最初にローカル スコープが検索され、次に上位スコープが検索されます。最初のコードの関数では変数のスコープが定義されていないため、上位のスコープ(グローバルスコープ)を検索してその値を出力します。ただし、変数のスコープは 2 番目のコードの関数内で定義されているため (変数がコンソールの後または前に定義されていても、変数のスコープはこのスコープ内にあるとみなされます)、上位レベルのスコープは存在しなくなりました。検索され、スコープが直接出力されます。しかし、残念ながら、この時点ではローカル変数 i には値が割り当てられていないため、出力は未定義です。
//所以根据函数作用域的意思,可以将上述第二段代码重写如下: var scope="global"; function t(){ var scope; console.log(scope); scope="local" console.log(scope); } t();
関数スコープの特性により、ローカル変数は常に関数本体全体で定義されます。変数宣言を関数本体の先頭に「進める」ことができます。
var b; //第1步 function fun(){ b = "change"; } alert(b);//输出undefined,由于第1步只定义未赋值 var b; //第1步 function fun(){ b = "change"; } fun(); //调用上述函数 alert(b); //输出change
var を使用して変数を宣言する場合、作成される属性は構成できません。つまり、delete 演算子を使用して属性を削除することはできません。
2. スコープインスタンス
<html> <head> <script type="text/javascript"> function buttonInit(){ for(var i=1;i<4;i++){ var b=document.getElementById("button"+i); b.addEventListener("click",function(){ alert("Button"+i);},false); } } window.onload=buttonInit; </script> </head> <body> <button id="button1">Button1</button> <button id="button2">Button2</button> <button id="button3">Button3</button> </body> </html>
登録イベントが終了すると、i の値は 4 になります。ボタンがクリックされると、イベント関数は function(){alert("Button"+i);} になります。この匿名関数には i がありません。このとき、i の値は 4 なので、「button4」が表示されます。
3. JavaScript クロージャー
js では、クロージャは主に、スコープ チェーン、ガベージ (メモリ) リサイクル メカニズム、関数のネストなど、js の他のいくつかの機能に関係します。
1. スコープ チェーン: 簡単に言うと、スコープ チェーンは、関数を定義するときに、使用される変数の値を見つけるために作成されるインデックスです。その内部規則は、関数自体のローカル変数を先頭に置くことです。 2 番目に独自の親関数に変数を配置し、さらに後ろの次の高レベル関数に変数を配置するというように、グローバル オブジェクトまで続けます。関数内で変数の値をクエリする必要がある場合、js インタープリターは先頭のローカル変数から始めてスコープ チェーン内を検索します。対応する変数が見つからない場合は、次のレベルのチェーン内を検索します。変数が見つかったら、それ以上先に進まないでください。必要な変数が最後に見つからない場合、インタプリタは未定義を返します。
2. Javascript のガベージ コレクション メカニズム: Javascript では、オブジェクトが参照されなくなった場合、そのオブジェクトは GC によってリサイクルされます。 2 つのオブジェクトが相互に参照し、サードパーティによって参照されなくなった場合、相互に参照している 2 つのオブジェクトもリサイクルされます。関数 a は b によって参照され、b は a の外側の c によって参照されるため、関数 a は実行後にリサイクルされません。クロージャを構築します。これらの変数はメモリ コレクターによってリサイクルされません。内部関数が呼び出されない場合にのみ、クロージャは破棄され、クロージャによって参照される変数は次のメモリによってリサイクルされません。
3. クロージャを使用すると、入れ子になった関数構造が機能します
4. js クロージャーを使用してループ バインディング イベントを実装します
<html> <head> <title>闭包</title> </head> <body> <ul id="list"> <li>第1条记录</li> <li>第2条记录</li> <li>第3条记录</li> <li>第4条记录</li> <li>第5条记录</li> <li>第6条记录</li> </ul> <script type="text/javascript"> function tt(nob) { this.clickFunc = function() { alert("这是第" + (nob + 1) + "记录"); } } var list_obj = document.getElementById("list").getElementsByTagName("li"); //获取list下面的所有li的对象数组 for (var i = 0; i<= list_obj.length; i++){ console.log(list_obj[i]) list_obj[i].onmousemove = function(){ this.style.backgroundColor = "#cdcdcd"; } list_obj[i].onmouseout = function() { this.style.backgroundColor = "#FFFFFF"; } //list_obj[i].onclick = function() { // alert("这是第" + i + "记录"); //不能正常获取 alert出来的都是:“这是第6记录” //} var col = new tt(i); //调用tt函数 list_obj[i].onclick = col.clickFunc; //执行clickFunc函数 } </script> </body> </html>
以上がこの記事の全内容です。JavaScript プログラミングを学習する皆さんのお役に立てれば幸いです。