6

JavaScript スコープ ルールを理解しようとしています。私が教科書やドキュメンテーションで読んだことは紛らわしいです。

JavaScript は静的 (または字句) スコープの言語のようです。変数名を変数 (定義) にバインドしようとすると、コードの字句構造が使用されます。

実行コンテキストは、コール スタックのスタック フレームに似ているようです。各実行コンテキストには、(関連する関数の) すべてのローカル変数が定義される変数オブジェクトがあります。これらの変数オブジェクトは、スタックの一番上にある変数オブジェクトからスタックの一番下にある変数オブジェクト (ウィンドウ オブジェクト) への「スコープ チェーン」を提供するために互いにリンクされています。このスコープ チェーンは、変数名を変数にバインドする際に上から下に検索されます。これは、C/C++/Java などの静的スコープの言語に非常に似ています。

C/C++/Java に関して重要な違いが 1 つあります。次の例に示すように、スタック フレームがコール スタック上にない関数で定義された変数にアクセスできます。

var color = "red";
var printColor;

function changeColor() {
    var color = "green";

    printColor = function(msg) {
        alert(msg + color);
    }
    printColor("in changeColor context, color = ");  // "green"
}

changeColor();

// stack frame for "changeColor" no longer on stack
// but we can access the value of the variable color defined in that function

printColor("in global context, color = ");  // "green"

私はこれを正しく理解していますか?他に注意すべき問題はありますか?

前もって感謝します

4

2 に答える 2

3

これは実際、C/C++ と JavaScript の大きな違いです。JavaScript は、参照がカウントされ、ガベージ コレクションが行われる言語です。つまり、オブジェクトへの参照がなくなった場合、オブジェクトはエンジンによって回収される可能性があります。割り当てる関数printColorは、C や C++ の場合とは異なり、それ自体はスタック上にありません。動的に割り当てられ、現在のスコープ外の変数に割り当てられます。そのため、制御フローが から戻るとき 、無名関数は 、外部が参照しchangeColorているため参照カウントは1printColorのままであり、外部スコープから使用できます。

したがって、あなたの例はスコープの問題ではありません.の関数スコープのprintColor で宣言することは明らかです changeColor。を定義する changeColorと 、上位値 が新しい関数スコープに閉じられ、アクセス可能になります。Combatが言ったように、 の 2 番目の内部定義に a を追加するprintColorと 、 最初 に宣言したものが になり、その関数ブロックの外ではアクセスできなくなります。varprintColorprintColor

その他の注意すべき問題に関しては、はい、かなりの数の問題がありますが、最初の投稿についての私のコメントを参照してください。

于 2012-06-21T23:54:14.277 に答える
1

それは常に、関数が呼び出されたときではなく、定義されたときにスコープチェーンで実行されるレキシカルスコープに帰着します。

無名関数は、関数 changeColor のグローバル スコープではなくローカル スコープで定義されます。したがって、再度実行すると、関数 changeColor のローカル スコープにリストされている緑色が出力されます。

于 2014-11-18T09:01:49.203 に答える