JavaScript クロージャ
JavaScript クロージャ
クロージャとは
クロージャ、クロージャの公式説明は次のとおりです: 多くの変數を含む式 (通常は関數) とこれらの変數をバインドする環(huán)境。つまり、これらの変數も一部です表現の。クロージャの特徴:
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 回だけ実行されるようにする必要もあります。
閉鎖が必要です。