22

私はしばらくの間javascriptで作業していて、通常、深層構造または「名前空間」内で宣言された関数のプロパティの値をキャッシュするためだけにこのようなことをします

//global scope
(function ($, lib) {
  //function scope 1
  var format = lib.format, // instead of calling lib.format all the time just call format
    touch = lib.pointer.touch, //instead of calling lib.pointer.touch each time just touch
    $doc = $(document),
    log = logger.log; //not console log...


  $doc.on('app:ready', function () {
    //function scope 2
    $doc.on('some:event', function (e) {
      //function scope 3
      //use the cached variables
      log(format('{0} was triggered on the $doc object', e.type);
    });

    $doc.on(touch, function (e) {
      //function scope 3
      log(format('this should be {1} and is... {0} ', e.type, touch);
    });
  }); 
}(jQuery, lib));

私はそれをしていました:

  • 私と同じように怠惰ですが、タッチを書くことはlib.pointer.touchを書くことよりも魅力的であるように見えます。ただし、派手なオートコンプリートを備えた強力なIDEがこれに役立つ場合でも、タッチは短くなります。
  • 最小化子はその単一のプライベート変数を単一の文字変数に変換できるので、それは私にとっても理にかなっています(私は知っています、私は知っています、すぐに最適化することはありませんが、これは安全だと思います)

そのように書かれたすべてのコードは、モバイルデバイスとデスクトップブラウザで適切に実行されるように見えるので、安全な方法のようです(「方法」では、しゃれが意図されています)。しかし、これはクロージャに依存しているので、内部関数は、私が疑問に思っていたと宣言されたコンテキストを保存するためにクロージャを作成する必要があります...

  • 関数が外部コンテキストからの変数(自由変数)を使用しない場合...クロージャーコンテキストはまだ保存されていますか?(または、iaツリーが木に落ちて、誰もそれを聞くことができない場合でも、クラッシュ音が鳴りますか?hehe)ECMAは保存が必要かどうかについて何も言及していないため、これはjavascriptエンジン間で異なる可能性があることを認識しています外部からの変数にアクセスしない場合のコンテキストかどうか。

  • 上記の式が真の場合...このコードブロックはより効率的ですか?

    //global scope
    (function ($, lib) {
      //function scope 1
      var format = lib.format,
        touch = lib.pointer.touch,
        $doc = $(document),
        log = console.log;
    
      $doc.on('app:ready', function () {
    
        (function ($doc, touch, lib, format) {
          // since all the variables are provided as arguments in this function
          // there is no need to save them to the [[scope]] of this function
          // because they are local to this self invoking function now
          $doc.on('some:event', function (e) {
            //function scope 3
            //use the cached variables
            log(format('{0} was triggered on the $doc object', e.type);
          });
    
          $doc.on(touch, function (e) {
            //function scope 3
            log(format('this should be {1} and is... {0} ', e.type, touch);
          });
        }($doc, touch, lib, format));      
    
      }); 
    
    }(jQuery, lib));
    

それらの変数を自己即時呼び出し関数に渡すので、より効率的ですか?その新しい関数を作成するコストは、コードに影響を及ぼしますか(負または正)?

  • 信頼できる方法でJavaScriptライブラリのメモリ消費量を適切に測定するにはどうすればよいですか?私は100xの小さなjavascriptモジュールをすべて即時自己呼び出し関数内に持っており、主に変数がグローバルコンテキストにリークするのを防ぎます。したがって、これらはすべて、上記のコードブロックと非常によく似たモジュールにラップされています。

  • 変数を使用する場所の近くで変数の宣言を繰り返す必要がある場合でも、変数をより近くにキャッシュする方が効果的でしょうか?

  • 現在のローカルコンテキストにない変数を探すと、エンジンは最初に親スコープを調べて、そのレベルのすべての変数を反復処理するように感じます...レベルごとの変数が多いほど、パフォーマンスが低下する可能性があります変数の場合。

  • 内部クロージャから未定義の変数を見つけようとすると、最もコストがかかります。これは、定義上、変数は最初に親スコープでグローバルスコープまで検索され、見つからない場合はエンジンが最終的にグローバルスコープに到達するためです。本当?エンジンはこの種のルックアップを最適化していますか?

結局のところ...コードを読みにくくし、最初のアプローチを使用して最終出力のサイズを最小化することに少し慣れているため、2番目の例としてコードを実装したくないことはわかっています。私の質問は好奇心に動機付けられており、JavaScriptのこの本当に素晴らしい機能をもう少しよく理解しようとしています。

このテストに応じて...

http://jsperf.com/closures-js

2番目のアプローチの方が速いようです。しかし、非常識な回数を繰り返す場合にのみ明らかです...現在、私のコードはその回数の反復を行いません...しかし、おそらく私のコーディング方法のために、より多くのメモリを消費しています...

更新:この質問は大きすぎると私に指摘されています。細かく分割してごめんなさい。私が言ったように、この質問は主に好奇心によって動機付けられました、パフォーマンスはモバイルデバイスでさえ無視できるようです。フィードバックをありがとうございます。

4

1 に答える 1

15

時期尚早の最適化だと思います。ほとんどの場合、パフォーマンスが問題にならないことは既にご存じでしょう。タイトなループでも、パフォーマンスはそれほど低下しません。クロージャーから不要な変数を削除することで、Chrome が始めたように、JavaScript エンジンが独自に最適化できるようにします。

重要なことの 1 つは、不要な最適化によってコードを読みにくくしないことです。あなたの例はかなり多くのコードを必要とし、開発を妨げています。場合によっては、アプリの特定の部分がより多くのメモリ/パフォーマンスを消費することがわかっているため、コードを読みにくくする必要がありますが、その時点でのみそうする必要があります。

次のコードに (Chrome で) ブレークポイントを追加すると、変数がクロージャーから最適化されていることがわかります。スコープ変数http://jsfiddle.net/4J6JP/worldの下の「クロージャー」ノードを見てください。1/

ここに画像の説明を入力.

(function(){
   var hello = "hello", world="world";
    setTimeout(function(){
        debugger;
        console.log(hello);
    });
})()

その内部関数に eval を追加すると、すべての賭けがオフになり、クロージャーを最適化できないことに注意してください。

于 2013-02-20T18:51:51.973 に答える