2012-06-21 8 views
5

JavaScriptスコープルールを理解しようとしています。私が教科書やドキュメンテーションで読んだことは混乱しています。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

今日、非常に徹底的にポストヒットしたHN:[JavaScriptの実行コンテキストとスタックは何ですか](http://davidshariff.com/blog/what-is-the-execution-context-in- javascript /) –

+2

これは* closure *と呼ばれます。 'printColor'に割り当てた関数は、関数が終了した後でも' changeColor'で定義されたすべての変数にアクセスできます。私はこれがCでどのようになっているのか分かりません。 –

+0

@FelixKling。しかし、changeColorはグローバルスコープでも定義されているため、スコープはガベージコレクションされません。 – webduvet

答えて

2

これは確かにC/C++とJavaScriptとの間の大きな違いである:JavaScriptはオブジェクトが エンジンによって回収することができることを意味する参照カウント、ガベージコレクション言語、 である場合、それらもはやそれらへの参照がありません。 printColorに割り当てた関数は、それ自体がスタックにはありません。 はCまたはC++になります。動的に割り当てられ、 に現在のスコープ外の変数が割り当てられます。 changeColorから制御フロー戻り、匿名関数は依然として外側printColorので の参照カウントを有するときに、それを指し、したがって、それは、外側 スコープから使用可能です。

だから、あなたの例では、スコープの問題のそれほどではありません - それはあなたがchangeColorの関数スコープの外 printColorを宣言することは明らかです。 changeColorと定義すると、新しい機能のスコープには closesの上位値 printColorがアクセス可能になります。あなたは printColorの第二、内側の定義にvarを追加した場合と同様に 戦闘は、言った、それは shadow最初 printColorよ、あなたが宣言され、その機能 ブロックの外側からアクセスできなくなります。

これまで知っておかなければならない問題はかなりありますが、私の コメントを参考にしてください。

+0

悲しいかな、私は質問を誤解しているかもしれませんが、私はまだ水を保持していると思います。 –

+0

printColorがスタックにないと言うと、私はあなたがprintColorを表すオブジェクトを意味するものと推測します。 printColorが呼び出されると、その実行コンテキスト/スタックフレームがスタックにプッシュされます。それとも私はそれが間違っている? – asterix

0

関数であるレキシカルスコープには常にスコープチェーンが定義されていて、スコープチェーンが呼び出されたときには実行されません。

匿名関数は、グローバルスコープの代わりに関数changeColorのローカルスコープで定義されています。したがって、再度実行されると、関数greenのローカルスコープにリストされている緑色が表示されます。

関連する問題