jsのクローズドと変数のスコープです.
5200 ワード
jsのクローズドを理解するには、まずjs変数のスコープを明らかにする必要があります.次のいくつかの例について説明します.
「javascript高級プログラム設計」という本の匿名関数についても言及しています.「thisオブジェクト」は、実行時の関数に基づく環境バインディングの実行です.グローバル関数では、thisはwindowに等しく、関数がある対象となる方法で呼び出された時に、thisはその対象となります.しかし、匿名関数の実行環境は全体的に、そのthisオブジェクトは一般にwindowを指すためである.
明らかにobject.get Name Funnc()は匿名の関数ですので、そのthisはwindowを指しています.大域変数の中でnameを探します.
Objectはクラスと考えられます.this.nameの中のthisはObjectを指します.その中にnameの属性が含まれていますので、My Object、
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){ return this.name};
}
};
console.log(object.getNameFunc()()); // The Window
分析原因:「javascript高級プログラム設計」という本の匿名関数についても言及しています.「thisオブジェクト」は、実行時の関数に基づく環境バインディングの実行です.グローバル関数では、thisはwindowに等しく、関数がある対象となる方法で呼び出された時に、thisはその対象となります.しかし、匿名関数の実行環境は全体的に、そのthisオブジェクトは一般にwindowを指すためである.
明らかにobject.get Name Funnc()は匿名の関数ですので、そのthisはwindowを指しています.大域変数の中でnameを探します.
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return this.name;
}
};
console.log(object.getNameFunc()); // My Object
分析原因:Objectはクラスと考えられます.this.nameの中のthisはObjectを指します.その中にnameの属性が含まれていますので、My Object、
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return name;
}
};
console.log(object.getNameFunc()); // The Window
分析原因:getNameFunc函数中的name没有var定义,实际上是具有全局性,所以打印出 The Window
分析原因:var x = "globol value"; var getValue = function() { console.log(x); // "undefined" var x = "local value"; console.log(x); // "local value"; } getValue();
実は簡単です.varが変数を定義する時、実際にjsをロードする時、var xを作用領域の一番前に言及します.上記のコードは同じです.下は人がノートを勉強しています.よく書きました.これはリンクですvar x = "globol value"; var getValue = function() { var x; console.log(x); // "undefined" x = "local value"; console.log(x); // "local value"; } getValue();
クローズド(closure)はJavascript言語の一つの難点であり、その特色でもあり、多くの高級アプリケーションはクローズドによって実現されます.
以下は私の学習ノートです.Javascript初心者にとってはとても役に立ちます.
一、変数のスコープ
クローズドを理解するには、まずJavascriptの特殊な変数のスコープを理解しなければならない.
変数のスコープは、大域変数と局所変数の2つにすぎません.
Javascript言語の特殊な点は、関数内部で直接大域変数を読み取ることができることです.
var n=999
function f 1(){alert(n);)
f 1()///999
一方、関数の外部では当然、関数内の局所変数を読み取ることができません.
function f 1(){var n=999;}
alert(n)//error
関数内部で変数を宣言する場合は、必ずvarコマンドを使用してください.使わないなら、実際にグローバル変数を宣言しました.
function f 1(){n=999;}
f 1()
alert(n)//999
二、外部からローカル変数を読み取るにはどうすればいいですか?
様々な理由から関数内の局所変数を得る必要があります.しかし、前にも話しましたが、普通の状況ではできません.変通方法でしか実現できません.
それは関数の内部で、もう一つの関数を定義することです.
function f 1(){
var n=999;
function f 2(){alert(n)//999}
)
上のコードでは、関数f 2が関数f 1の内部に含まれており、f 1の内部のすべての局所変数は、f 2に対して可視である.しかし、逆にだめです.f 2内部の局部変数は、f 1に対しては見えません.これはJavascript言語特有の「連鎖作用領域」構造であり、サブオブジェクトは一段ずつ上に向かってすべての親オブジェクトの変数を探します.したがって、親オブジェクトのすべての変数は、子オブジェクトに対しては見えますが、逆は成立しません.
f 2は、f 1の局所変数を読み取ることができるので、f 2を戻り値とすると、f 1の外部で内部変数を読み出すことができるのではないでしょうか?
function f 1(){
var n=999;
function f 2(){alert(n); )
return f 2;
)
var reult=f 1()
レスリング()///999
三、クローズドの概念
前のセクションのコードのf 2関数は、閉じられています.
各種の専門文献の「クローズド」の定義はとても抽象的で、分かりにくいです.私の理解では、クローズドとは他の関数の内部変数を読み取ることができる関数です.
Javascript言語では、関数内部のサブ関数だけが局所変数を読み取ることができるので、クローズドを単に「関数の内部に定義された関数」と理解することができます.
したがって、本質的には、クローズドとは、関数の内部と関数の外部をつなぐ橋のことである.
四、クローズドの用途
クローズドは多くのところで使えます.その最大の用途は二つあります.一つは前に述べた関数内部の変数を読み取ることができます.もう一つはこれらの変数の値を常にメモリに保存させます.
この言葉はどうやって理解しますか?下のコードを見てください.
function f 1(){
var n=999;
nAdd=function(){n+=1}
function f 2(){alert(n);)
return f 2;
)
var reult=f 1()
レスリング()///999
nAdd()
レスリング()///1000
このコードの中で、resultは実はクローズドf 2関数です.全部で二回運行しました.一回目の値は999、二回目の値は1000です.これは、関数f 1の局所変数nがメモリに保存されており、f 1呼び出し後に自動的に消去されないことを証明している.
どうしてですか?f 1はf 2の親関数であり、f 2はグローバル変数を与えられ、f 2は常にメモリにあり、f 2の存在はf 1に依存しているため、f 1も常にメモリにあり、呼び出しが終了した後、ゴミ回収メカニズムによって回収されることはない.
このコードのもう一つの注目すべき点は、「nAdd=function(){n+=1]」という行であり、まずnAddの前にvarキーワードが使用されていないため、nAddは局所変数ではなくグローバル変数である.第二に、nAddの値は匿名関数であり、この匿名関数自体もクローズドであるため、nAddは相当であり、関数の外部で関数内部の局所変数を操作することができる.
五、クローズドを使う注意点
1)クローズドは関数の変数がメモリに保存されるため、メモリの消耗が大きいので、クローズドを濫用してはいけません.そうでないと、ウェブページの性能問題が発生し、IEでメモリのリークを引き起こす可能性があります.解決方法は、関数を終了する前に使用しないローカル変数をすべて削除します.
2)親関数の外部で、親関数の内部変数の値を変更します.したがって、親関数を対象として使用する場合は、クローズドをそのパブリックメソッドとして、内部変数をそのプライベート属性として扱い、親関数内部変数の値を勝手に変えないように注意してください.
六、思考問題
下記の2つのコードの運行結果を理解できれば、クローズドの運行メカニズムを理解してもいいはずです.
コードセグメント1
var name=「The Window」
var object={name:My Object}
get NameFun:function(){return function(){return this.name];
)
}
alert(object.get NameFun();
コードセグメント2
var name=「The Window」
var object={name:My Object}
get NameFun:function(){var that=this;return function(){return that.name];
)
}
alert(object.get NameFun();
(終わり)