3

Javascript でスコープ チェーンを使用して変数を解決する方法を説明している記事をいくつか見ました。

それらはすべて、変数は実行時にスコープチェーンをたどり、その名前の変数を繰り返し探して解決されると言います。また、その主張を裏付けるグラフも見ました。これは、チェーンの上位にある変数のパフォーマンスが悪いことを示しており、アクセス時間は距離のスコープ レベルの数にほぼ比例しています。

アクセス時間が一定でない理由がわかりません。特定の場所の変数名は、一定の辞書式バインディングを作成します。そこで私は単純に、実行コンテキストへの参照と、その実行コンテキストに関連する変数への参照を使用して、対応するランタイム変数参照インスタンスを表すことができるはずだと考えました。

なぜそうではないのか、いくつかの光を当てることができますか?

4

1 に答える 1

2

V8 のような今日の JIT コンパイラは、これの一部を最適化する可能性がありますが、基本的には次のように動作します。

たとえば、このような関数がたくさんあります..

function foo() {
    function bar() {
    }
}

これにより、 のクロージャfooと のクロージャが生成されbarます。変数ルックアップが機能するためには、インタプリタはバウンディング クロージャを経由して変数を見つける必要があります。

たとえばbar、変数は次のように定義できます。

  • 内部機能bar
  • 中身foo
  • グローバル スコープ内

したがって、変数がどれだけ上にあるかに応じて、コードはそれらすべてをチェックする必要があります。

もちろん、ルックアップが常に一定である変数名のテーブルのようなものを保持することもできますが、別の問題に直面します: シャドウ変数です。

ネストされた関数内の変数に同じ名前を共有できます。そのため、名前に基づく変数のルックアップ テーブルを作成する際に問題が発生します。もちろん、使用可能な変数に基づいて各関数のルックアップ テーブルをコピーして作成することもできますが、これは速度とメモリ消費のトレードオフになります。

今日の JS エンジンの完全な詳細や実装を知らなければ、なぜこのように設計されたのかを説明するのは困難です。ただし、メモリを消費せずに問題なく動作するという点で、十分に妥当なシステムだと思います。また、変数検索を高速化したい場合は、変数を関数のローカル スコープに割り当てることが常に可能であるため、必要に応じて手動で最適化できます。

于 2013-11-09T01:27:25.403 に答える