4

スコープチェーンの概念を要約すると、次のようになります。

Webページがロードされるとすぐに、Javascriptは関数定義を見つけて、それぞれにいわゆる変数オブジェクトを作成します。各VOは、各ローカル変数(またはグローバル)を参照する必要があるため、グローバルコンテキストまで、最初の祖先の関数から開始します。各関数のスコープチェーンは、Scopeという関数プロパティに格納されます。

さらに、関数が呼び出されると、新しいオブジェクトが作成されます:アクティベーションオブジェクト

これは何ですか?:

これは、「引数」オブジェクトと仮パラメーターを含むすべての関数内部の変数オブジェクトを参照する役割を担う変数オブジェクト(実際にはVO)のように機能します。

もちろん、関数の祖先の変数オブジェクト+関数のアクティベーションオブジェクトで構成されるチェーンのそれぞれは、少なくともすべての変数をundefined最初にマップします。次に、実行が進行する限り、値(参照される変数に対応)を更新することによって進化します。

ただし、Activation Objectは、 Argumentsオブジェクトが含まれているという理由だけで変数オブジェクトとは異なり、この事実により、関数が呼び出される前に作成できなくなることに気付きました。

それで、なぜJavascriptエンジンを構築した人々が、関数の定義ステップで各アクティベーションオブジェクトを割り当てなかったのだろうか。したがって、関数が呼び出されるときに、それがすでに存在するため、独自の特定のアクティベーションオブジェクトを作成する必要はありません。エンジンは、関数の実行の最後に対応する引数オブジェクトをクリアするだけなので、このオブジェクトへの次の呼び出しは副作用なしに可能になります。

パフォーマンスが向上する可能性はありますか?実際、呼び出しごとにアクティベーションオブジェクト全体を再作成すると、消費される可能性があります。または、この提案に問題がありますか?

4

2 に答える 2

6

アクティベーションオブジェクトは、関数呼び出しのコンテキストを表します。各呼び出しには、独自のオブジェクトが必要です。それらは閉鎖などを可能にするものです。

これは、CまたはC++関数の呼び出しに割り当てられたスタックフレームに類似していると考えてください。

編集—関数の例を次に示します。

function makeCounter( count ) {
  return function() {
    return count++;
  };
}

今、私はそれでカウンター関数を作ることができます:

var counter1 = makeCounter(1);
alert(counter1()); // alerts "1"
alert(counter1()); // alerts "2"

別のものを作ったらどうなりますか?

var counter100 = makeCounter(100);
alert(counter100()); // alerts "100"

両方の呼び出しがmakeCounter()単一のargumentsインスタンスを共有した場合、後で「counter1()」を呼び出したときにどうなりますか?

于 2012-10-30T12:49:28.903 に答える
0

いつでも進行中の関数の複数の呼び出しがある可能性があるため、関数ごとに1つのアクティベーションオブジェクトを呼び出し全体で再利用することはできません。この明らかな例の1つは、再帰です。

たとえば、関数ごとに1つの熱心に割り当てられたAOを持つことができるので、少なくとも最初の呼び出しでそれを使用できますが、この種のメカニズムは、せいぜい名目上のパフォーマンスの向上の概念を複雑にするだけだと思います(メモリのトレードオフも行います)。

于 2021-08-18T09:50:36.540 に答える