7

Chromeデベロッパーツール内でこのコードを実行すると、次のようになります。

var test = (function () {

  var publicFunction,
      privateFunction1,
      privateFunction2;

  privateFunction1 = function privateFunction1() {
    return true;
  };

  privateFunction2 = function privateFunction2() {
    return true;
  };

  publicFunction = function publicFunction() {
    privateFunction1();
    debugger;
  };

  return {
    publicFunction: publicFunction
  };
})();

privateFunction1ブレークポイントでスコープ内にあるのに、そうでないのはなぜprivateFunction2ですか?

Chrome開発ツールのスクリーンショット

4

1 に答える 1

4

興味深い質問です。

privateFunction2 範囲内ですpublicFunctionが、publicFunction実際に使用することはありません。デバッガーに表示されているのは、V8 (Chrome の JavaScript エンジン) がさまざまな理由 (メモリ使用量の最小化など) でクロージャーの内容を最適化しているためだと思います。

理論的には、仕様によると、 はpublicFunction定義されているスコープ内のすべてのシンボルを閉じます (永続的な参照があります)。具体的には、最も外側の匿名関数の呼び出し用に実行コンテキストが作成され、その実行コンテキストには、暗黙的な匿名参照を持つバインディング オブジェクトが関連付けられたレキシカル環境があります。そのバインディング オブジェクトには、(理論的には) 、、、およびその他のいくつかの名前 (など) を持つプロパティがあります。publicFunctionpublicFunctionprivateFunction1privateFunction2arguments

しかし問題は、publicFunctionは実際には何も参照せずprivateFunction1、そのためのコードが配置されているため、他のものを参照できないということです。他のものを参照するには、そのコードを変更する必要があり、もちろん V8 は別の決定を下します。のコードにpublicFunctioneval(string)ornew Function(string)呼び出しがないため、V8 は参照するシンボルの静的解析を自由に実行できます。つまり、デバッガーがなければ、バインディング オブジェクトがこれらの他のプロパティを保持しても意味がありません。それらは決して使用されません。

V8 は積極的に最適化するコンパイラ (はい、コンパイラ) であるため、明らかに、実行コンテキストのバインド オブジェクトから無効なプロパティを削除します。

publicFunction何にでも使えるものを追加するとprivateFunction2、コンソールから参照できるようになりますprivateFunction1

于 2013-02-13T13:12:28.420 に答える