JavaScript クロージャ
JavaScript クロージャ
クロージャとは
クロージャ、クロージャの公式説明は次のとおりです: 多くの変数を含む式 (通常は関数) とこれらの変数をバインドする環境。つまり、これらの変数も一部です表現の。クロージャの特徴:
1. 関数変数への参照として、関数が戻ったときにアクティブ化されます。
2. クロージャとは、関数が戻ったときにリソースを解放しないスタック領域です。
簡単に言えば、JavaScript では内部関数の使用が許可されています。つまり、関数定義と関数式は別の関数の関数本体内に配置されます。さらに、これらの内部関数は、すべてのローカル変数、パラメータ、およびそれらが存在する外部関数で宣言された他の内部関数にアクセスできます。クロージャは、これらの内部関数の 1 つが、それらを含む外部関数の外側で呼び出されるときに形成されます。
2. クロージャを書いて使用するいくつかの方法
まず第一に、JS のすべてがオブジェクトであり、関数もオブジェクトの一種であることを理解する必要があります。まず、クロージャを記述する 5 つの方法を見て、クロージャとは何かを簡単に理解しましょう。これについては後で詳しく説明します。
//最初の書き方
function Circle(r) { this.r = r; } Circle.PI = 3.14159; Circle.prototype.area = function() { return Circle.PI * this.r * this.r; } var c = new Circle(1.0); alert(c.area());
この書き方は特別なものではなく、関数にいくつかの属性を追加するだけです。
//2番目の書き方
var Circle = function() { var obj = new Object(); obj.PI = 3.14159; obj.area = function( r ) { return this.PI * r * r; } return obj; } var c = new Circle(); alert( c.area( 1.0 ) );
この書き方は、変数を宣言し、その変数に値として関数を代入する方法です。
//3 番目の書き方
var Circle = new Object(); Circle.PI = 3.14159; Circle.Area = function( r ) { return this.PI * r * r; } alert( Circle.Area( 1.0 ) );
このメソッドは、新しいオブジェクトを作成し、そのオブジェクトにプロパティとメソッドを追加するという方法でよく理解されています。
//4番目の書き方
var Circle={ "PI":3.14159, "area":function(r){ return this.PI * r * r; } }; alert( Circle.area(1.0) );
この方法はよく使われており、最も便利です。 var obj = {} は空のオブジェクトを宣言します。
//5番目の書き方
var Circle = new Function("this.PI = 3.14159;this.area = function( r ) {return r*r*this.PI;}"); alert ( (new Circle()).area(1.0) ); 正直、この書き方は使ったことがないので参考にしてください。
一般に、上記の方法のうち、2 番目と 4 番目の方法がより一般的であり、習慣に応じて選択できます。
上記のコードにはJSでよく使われるプロトタイプが出てきますが、プロトタイプって何に使うのでしょう?以下を見てみましょう: var dom = function(){
};
dom.Show = function(){
alert("Show Message");
};
dom.prototype.Display = function(){
alert("Property Message");
};
dom.Display(); //error
dom.Show();
var d = new dom();
d.Display();
d.Show(); //error
変数のライフサイクル
グローバル変数のスコープはグローバルです。つまり、グローバル変数は JavaScript プログラム全体のあらゆる場所にあります。 関数内で宣言された変数は関数内でのみ機能します。これらの変数はローカル変数であり、そのスコープはローカルです。関数のパラメータもローカルであり、関数内でのみ機能します。
カウンターのジレンマ
いくつかの値をカウントしたい場合、カウンターはすべての関数で使用できると想像してください。
グローバル変数と関数を使用してカウンターの増分を設定できます:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>全局变量计数。</p> <button type="button" onclick="myFunction()">计数!</button> <p id="demo">0</p> <script> var counter = 0; function add() { return counter += 1; } function myFunction(){ document.getElementById("demo").innerHTML = add(); } </script> </body> </html>
add() 関数が実行されるとカウンター値が変化します。
しかし、ここで問題が発生します。add() 関数が呼び出されていなくても、ページ上のどのスクリプトでもカウンターを変更できるのです。
関数内でカウンターを宣言した場合、関数を呼び出さずにカウンターの値を変更することはできません:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>局部变量计数。</p> <button type="button" onclick="myFunction()">计数!</button> <p id="demo">0</p> <script> function add() { var counter = 0; return counter += 1; } function myFunction(){ document.getElementById("demo").innerHTML = add(); } </script> </body> </html>
上記のコードは正しく出力されず、add() 関数を呼び出すたびにカウンターが設定されます1に。
JavaScript の組み込み関数がこの問題を解決できます。
JavaScript 組み込み関数
すべての関数はグローバル変数にアクセスできます。
実際、JavaScript では、すべての関数がその上のスコープにアクセスできます。
JavaScript はネストされた関数をサポートしています。ネストされた関数は、上位レベルの関数変数にアクセスできます。
この例では、埋め込み関数 plus() は親関数のカウンター変数にアクセスできます:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>局部变量计数。</p> <p id="demo">0</p> <script> document.getElementById("demo").innerHTML = add(); function add() { var counter = 0; function plus() {counter += 1;} plus(); return counter; } </script> </body> </html>
plus() 関数に外部からアクセスできれば、カウンターのジレンマを解決できます。
counter = 0 が 1 回だけ実行されるようにする必要もあります。
閉鎖が必要です。