すべてのJavaScript関数は、スコープチェーン全体の変数環境を継承し、それ自体を含むことで同じように動作します。これは、匿名関数と名前付き関数の両方で同様です。
外部環境への参照の連鎖は、関数が全く異なるスコープに渡されても、各関数にとどまります。
従来は、内部クロージャが存在し続ける限り、任意のチェーン内のすべての変数に参照が保持されていました。コードをコンパイルする現代のブラウザでは、どの変数が実際に参照されているかを分析し、それらの変数のみが保持され、参照されなくなった他のものがガベージコレクションされる可能性があります。
しかし、無名関数が無駄である他の状況があります。
ここでは、コードの共通のビットがあります:
for(var i = 0; i < 100; i++) {
(function(j) {
setTimeout(function() { console.log(j); }, 1000);
})(i);
}
これは、ときにあなたがループの中に同一の機能を100回を再現しているので、匿名関数は、もう少し無駄という名前の関数よりもある状況です名前付きのものを再利用することができます。
function setConsole(j) {
setTimeout(function() { console.log(j); }, 1000);
}
for(var i = 0; i < 100; i++) {
setConsole(i);
}
これは閉包オーバーヘッドと全く同じですが、新しい変数環境を作成するための関数を1つしか作成していないため、より効率的です。
http://jsperf.com/immediate-vs-named(jsPerfの場合は@Felix Klingありがとうございます。)
特にクロージャに関して、はい、いくつかの永続的な参照によって閉鎖を維持する限り、オーバーヘッドがあります。可能であればこれを避けるのは良いことだが、それに強くはないといいだろう。時には、スコープチェーンに追加された新しい変数環境が単なるベストソリューションです。
EDIT:Here's an article from Google。具体的には、を参照してください。閉鎖を伴う落とし穴の回避。スコープチェーンを拡張することによるパフォーマンスの影響、および名前の付いた関数よりも匿名関数が「遅い」という主張については、
優秀な質問です。私はその日のために票を使い切った - 他の誰かが私のために+1できる? –
@Michael既にしました。素晴らしい質問。 –
クロージャーの実装*についても同様の質問がありましたが、まだ満足のいく答えで見ています。つまり、現代の* JavaScriptエンジンは、アクセス可能なオブジェクトを囲むだけのスマートなものですか?明らかに、この最適化は 'eval'の存在下で適用するのは現実的ではありません。 –