5

最近、私はこれを読んだことがあります。(これらのアドバイスは変数スコープが動的なCommonLispユーザに与えられたように)「Javascript:閉鎖変数へのアクセスが遅い理由

var a = 'a'; 
function createFunctionWithClosure() { 
    var b = 'b'; 
    return function() { 
    var c = 'c'; 
    a; 
    b; 
    c; 
    }; 
} 

var f = createFunctionWithClosure(); 
f(); 

fが呼び出されたときに、aを参照すると、cを参照するよりも遅くなる、bを参照するよりも遅いです。

それはローカル変数にCを参照すると、Bよりも高速であることは極めて明白だが、iterpreterが適切に書かれている場合(動的スコープなし - チェインハッシュテーブルのルックアップのようなもの。)の速度差はわずかでなければなりません限界。か否か?

答えて

4

あなたはそうです。現代のJSエンジンは、scope chain lookupprototype chain lookupのように多くを最適化します。 AFAIKというエンジンは、下にアクセスノードを持つ何らかのハッシュテーブルを保持しようとします。

これは、eval()(明示的または暗黙的、たとえばsetTimeout)またはtry-catch句またはa with statementが呼び出されない場合にのみ機能します。このような構造のため、インタプリタはデータにアクセスする方法を確かめることができず、実際にはすべての親コンテキストvariable/activation objectsをクロールして、検索された変数名を解決しようとする古典的なscope chain lookupに "フォールバック"する必要があります。 このプロセスでは、処理が開始された場所から「遠くに」あるオブジェクト/名前には、より多くの時間がかかります。つまり、global objectのデータへのアクセスは常に最も遅くなります。スニペットで

aのルックアップ処理について説明ルックアップ手順はのECMAScript Editionの262第3版のためである

anonymous function -> Execution Context -> Activation Object (not found) 
anonymous function -> Execution Context -> [[ Scope ]] 
    - createFunctionWithClosure 
    - global scope 
createFunctionWithClosure -> Activation Object (not found) 
global scope -> Variable Object (found) 

のように行くだろう。 ECMAscript Edition 5にはいくつか根本的な変更があります。

+0

長寿(と私の好奇心)については、v5でどのように変化しているのかを説明できますか? – Hogan

+0

匿名関数の中で 'var d = eval(" this ");'を実行すると、スコープチェーンルックアップはすべてのコンテキストをクロールして 'a'の参照を取得しますか?それとも 'this'を' d'に割り当てるのか? – headacheCoder

+0

@headacheCoder:これは、ある種の "古い"ブラウザで実行されると非常に可能です。しかし、実際にはこういった恐ろしい声明は決して行うべきではありません。最先端のブラウザは 'eval'を使って物事を最適化することさえできます。しかし、これらのブラウザーはとにかくES5仕様に従います。 – jAndy

関連する問題