The linked video explains why closure can inflict some performance hits starting about 11:08.
基本的に、彼はネストされた各機能のために、それはスコープチェーンに別のオブジェクトを追加しますので、クロージャの外で変数にアクセスするにも時間がかかるだろうと言っています。
変数に関連付けられた値を見つけるためには、JavaScriptのinterprerは、次のプロセスに従います
- 1が機能しなかった場合場合は親スコープオブジェクト
- を検索し、ローカルスコープオブジェクト
- を検索します2が機能しなかった場合、親の親スコープオブジェクトを検索する
- 親スコープを検索し続けるまで
- グローバルスコープを検索する
- が見つからない場合は、未定義の変数エラーをスローします。
通常の関数では、変数を見つけるには、スコープチェーンの先頭を検索するだけです。一方、親変数を見つけるためのクロージャは、時にはいくつかのレベルの深さでスコープチェーンを検索する必要があります。 、それが中に3つのレベルアップトラバースしなければならない最も内側の関数から
function a (x) {
function b (y) {
return (function (z) {
return x + y + z;
})(y + y);
}
return b(x + 3);
}
、表現x + y + z
を評価する:あなたはこのようないくつかのクロージャを持っている場合たとえば、(これは非常に不自然な例であることに注意してください)スコープチェーンをxにすると、スコープチェーンを再び2つのレベルでyを見つけ出し、最後にzを1回見つける必要があります。合計で、の範囲内の6つのオブジェクトを検索して最終結果を返さなければなりませんでした。
のクロージャは、常に親変数にアクセスする必要があるため、クロージャでは避けられないものです。彼らがなければクロージャを使用する目的はありません。
また、Javascriptでは、関数、特にクロージャの作成にかなりのオーバーヘッドがあります。例えば、この非常に単純な閉鎖ください:
function a(x) {
return function (y) {
return x + y;
}
}
をそして、あなたはいくつかの異なる回それを呼び出す、この
var x = a(1);
var y = a(2);
var z = a(3);
alert(x(3)); // 4
alert(y(3)); // 5
alert(z(3)); // 6
のようにあなたはa
から返される関数は渡されたものを維持するために持っていることに気づくでしょう親関数が既に呼び出された後でも、親関数の引数として使用できます。これは、通訳者があなたが今までに呼び出されたすべての関数に渡したものを記憶しなければならないことを意味します。
覚えておいてください:時期尚早最適化はすべての悪の根源です。このビデオでは、JavaScriptのパフォーマンス向上について議論が行われていますが、ほとんどのJavaScriptを最適化する必要はありません。ユーザーがボタンをクリックした後に非同期に機能を呼び出すと、30msの応答速度と40msの応答速度の差に気づかれることはありません。 – zzzzBov
ここの答えはすべていいです。しかし、ビデオは数年前のことであり、かつてのように関連性がないかもしれないことを覚えておいてください。 –