4
window.onload = function() {
   var a = function(x) {
       console.log(x);
   };
   document.onclick = function() {
       a(1);
   };
   document.onkeyup = function() {
       a(2);
   };
};

なぜこれが機能するのかはかなりよく理解していますが、どのように機能するのかはわかりません。

window.onload 終了すると、aは破棄されますが、これを正しく理解していれば、より高いスコープで宣言されているため、参照されている関数は引き続きイベントハンドラーで使用できます。

インタプリタはバックグラウンドで関数への非表示の参照を保持しますか、それともインタプリタは何らかの形で関数をインライン化しますか?このタイプのコードは、グローバル変数を効率的に回避するためのものですか?ありがとう。

4

6 に答える 6

1

window.onload終了すると、破壊aされます...

その仮定は間違っています。別の関数内に関数を作成するときはいつでも、それらの内部関数はガベージコレクターが外部関数のスコープをクリーンアップするのをブロックします。

推奨読書:http ://www.ibm.com/developerworks/web/library/wa-memleak/

于 2013-02-04T08:17:06.077 に答える
0

これはあなたの質問に対する完全な答えではありませんが、それが役立つ場合は... Javascriptでのオブジェクトの存続期間は、通常、参照カウントによって制御されます。

この言語には、実際にはブロックスコープの概念はありません(ただし、関数スコープは利用できます)。オブジェクトは、参照が残っていない場合にのみ、バックグラウンドGCによって自動的にクリーンアップされます。したがって、オブジェクトの動作はa本質的に「安全」です。関数スコープが終了すると1つの参照が削除されますが、別の参照は残ります。

より詳細な答えは、特定のJavascriptエンジンの実装を複雑に調査する必要があります。おそらく、ここでの時間やスペースよりも詳細になります。

于 2013-02-04T08:09:07.117 に答える
0

これは「クロージャー」として知られています。つまり、「関数は、それが定義されているスコープ内のすべての変数にアクセスできる」という意味です。

この例では、2つのハンドラーがwindow.onload関数内で定義されているためa、このスコープ内にあるにアクセスできます。

そして、はい、インタプリタはすべてのクロージャをメモリに保持します。(afaik)
私はプロのプログラマーではないので、あまり権限がありません。しかし、私は通常、グローバルを避けるためにこれを行います。

MDNの閉鎖

于 2013-02-04T08:06:33.747 に答える
0

javascriptの変数内の関数またはそれらへの参照はオブジェクトの一種であり、通常のオブジェクトと同様に、それらへの参照を保持する関数または変数は、それらへの参照がなくなるまでガベージコレクションされません。特定のケースでは、ハンドラーa()よりも長く続く参照をいくつか作成しました。.onload()したがって、変数aは関数よりもはるかに長く持続します。この概念は「閉鎖」として知られています。

グーグルで「javascriptのクロージャ」という用語を検索すると、このようなトピックに関する多くの役立つ記事が見つかります。

于 2013-02-04T08:11:38.727 に答える
0

インタプリタはバックグラウンドで関数への非表示の参照を保持しますか、それともインタプリタは何らかの形で関数をインライン化しますか?

これは、すべてのjavascriptエンジンでグローバルに回答できるわけではありません。ただし、パーサーは、a定義する無名関数との両方について、関数への参照を保持する必要がdocument.onclickありdocument.onkeyupます。したがってa、すぐに破棄されることはなく、javascript変数スコープの制限によってのみアクセスできなくなります。

aこれが、エンジンが実際に適切に逆参照することが難しいため、クロージャがメモリリークにつながる可能性がある理由です。(これはIEエンジンの問題であり、注意深く処理されていない場合でも問題です)。aまた、変数にアクセスできないため、手動で逆参照できないため、このタイプのパターンから発生するメモリリークをすばやく修正することはできません。

この例も、関数を返さないためクロージャではありませんが、同じスコープ(および)aを共有しない関数内のローカル変数を参照するため、同じ種類の変数スコープの問題を扱います。document.onclickdocument.onkeyup

a関数オブジェクトを不必要に複製するため、エンジンが関数をインライン化しようとしないことを強く疑っています。ほとんどの場合、参照カウントが0に下がると(この例では、とが逆参照される(またはに設定される)pointerと、前述の参照カウントを簡単に破棄できるようになります。document.onclickdocument.onkeyupnullundefined

このタイプのコードは、グローバル変数を効率的に回避するためのものですか?

グローバル変数を回避することは常に良いことです。したがって、一般的には、グローバル変数を回避するための効率的な方法です。aすべての優れたエンジンも一度破壊する必要がdocument.onclickありdocument.onkeyup、参照が解除されます。

于 2013-02-04T08:16:45.760 に答える
0

window.onloadスコープまたはコンテキストオブジェクトは、ハンドラー内で最初の関数を宣言した瞬間にJavaScriptによって自動的に作成されます。このスコープオブジェクトは変数を保持しa、事実上、両方の無名関数に対して排他的になります。

この手法は、情報を隠蔽し、グローバル変数を作成する必要をなくすためによく使用されます。onloadコードが実行されると、他のコードはにアクセスできなくなりますa

于 2013-02-04T08:43:25.270 に答える