2011-07-07 4 views
15
var name = function(n) { 
    var digits = ['one','two','three','four']; 
    return digits[n]; 
} 

var namenew = (function() { 
    digits = ['one','two','three','four']; 
    return function(n) { 
     return digits[n]; 
    } 
}()); 

両方のバージョンで同じ結果が得られますが、2番目のバージョンは最初のバージョンよりもはるかに高速です。閉鎖したJavascriptのパフォーマンス

私が理解しているように、最初のバージョンは、2番目のバージョンが実行結果を格納するたびに関数を実行します。それが機能的な/規則的なOOPSプログラマとして私を混乱させるものです。

関数を内部コンテキストで保存するにはどうすればよいですか?フードの下で何が起こっていますか?いくつかのpls明確にすることはできますか?

+1

それは数字のリストを含むオブジェクト、プラスメソッドを作成しています。 –

答えて

13

この質問に対する真の答えは約3ページです。しかし私は可能な限り短くしようとします。 ECMA-/Javascriptはすべて約Execution ContextsObjectです。 ECMAscriptには、基本的な3種類のコンテキストがあります:Global contextFunction contextsおよびeval contextsです。

あなたが関数を呼び出すたびに、あなたのエンジンはそれ自身のfunction contextにそれを生成します。また、Activation objectと呼ばれるものもあります。この神秘的な目的は、少なくとも外から成るfunction contextの一部である:「この」コンテキスト値

がより存在してもよい

  • [スコープチェーン]
  • 起動対象
  • これらの3つはESの実装に必要です。しかし、トピックに戻る。関数コンテキストが呼び出された場合は、すべてparent contexts(またはより正確には、親コンテキストのActivation objects)が[[Scope]]プロパティにコピーされます。このプロパティは、(Activation-)Objectsを保持する配列のように考えることができます。現在、関数関連の情報は、Activationオブジェクト(仮パラメータ、変数、関数宣言)に格納されています。

    例では、digits変数は、namenewのアクティベーションオブジェクトに格納されています。 2番目の内部無名関数が作成されるとき、それはその[[Scope]]プロパティにActivation objectを追加します。digits[n]を呼び出すと、Javascriptは最初にその変数をその自身のアクティベーションオブジェクトで見つけようとします。それが失敗すると、検索はScopechainに行きます。私たちは外部関数からAOをコピーしたので、変数が見つかりました。

    私はすでに短い回答であまりにも多くを書いていますが、本当にそのような質問に良い答えを出すには、ここでESに関するいくつかの基本的な知識を説明しなければなりません。私はそれがちょうど実際に "フードの下で"起こっているアイデアを伝えるのに十分だと思います。(もっと知りたいことがたくさんあります。あなたはそれを求め


    、あなたはそれを得る:

    http://dmitrysoshnikov.com/ecmascript/javascript-the-core/

8

最初の関数は、実行するたびにdigitsを再作成します。それが大規模な配列の場合、これは不必要に高価です。

digitsは、namenewとのみ共有されたコンテキストに格納されます。 namenewが実行されるたびに、1回の操作(return digits[n])のみが実行されます。

このような例では、パフォーマンスに顕著な向上は見られませんが、非常に大きな配列/オブジェクト/関数呼び出しのパフォーマンスが大幅に向上します。

このようにクロージャを使用するOOPパースペクティブは、静的変数にデータを格納するのと同様です。


namenewが閉鎖機能の結果を受信して​​いることを忘れないでください。クロージャー自体はと一度だけ実行されます。

+0

残念ながら、あなたが言及したことはすべて理解しています。私が探しているのは、何が起きているのかということです。 'Under the hood' – Kiran