スコープその1
今JavaScriptを勉強しているんだけど,スコープはクロージャのベースともなる大事な仕様だと思ったのでいろいろ調べました。その備忘録です。
まだまだJavaScriptは初学者なので,ここ違うぞ!とか有りましたらコメント頂けると助かります。
そもそもスコープとは?
JavaScriptというよりプログラムの一般的な話でスコープとはコード中の変数や関数の名前解決を行う為の有効範囲です。
例えば,スコープ外で変数や関数が使われている場合,
function func() { var a = 'TEST'; return 0; } document.writeln(a);
実行してみるとエラーとなります。
関数内で宣言されているaは有効範囲が関数の中だけなので,トップレベル(どの関数の中でもない場所)でaという変数を使うことはできません。
スコープの種類
JavaScriptのスコープはグローバルスコープとローカルスコープの二種類があります。
C++等にある中括弧で囲まれたブロックのスコープはありません(例えばfor文の中で宣言した変数はfor文の外でも使えます)。
グローバルスコープ
グローバルスコープをもつ変数はコード上のあらゆる場所で使う事ができます。
関数の中で宣言されていない変数や関数がグローバルスコープをもつことになります。
// この変数aはグローバル var a; // このfunc関数はグローバル function func() { // この変数bや関数func2はグローバルではない var b; function func2() { } }
グローバルオブジェクト
グローバルスコープの仕組みはグローバルオブジェクトにあります。
JavaScriptのインタプリタはコードを実行する時,まずグローバルオブジェクトを作ります。
そしてグローバルスコープをもつ変数や関数は全て,このグローバルオブジェクトのプロパティとなります。
インタプリタが処理中に名前(変数あるいは関数)が出てくるとこのグローバルオブジェクトのプロパティから同じものがないか探します。
(ちなみにブラウザで動かす場合はグローバルオブジェクトはWindowオブジェクトの事です)
ローカルスコープ
関数の中で作られたローカル変数や関数がもつのがローカルスコープです。
その関数の中でのみ使うことができます。
function func() { var tmp = 0;// この関数の中で有効 document.writeln(tmp); }
スコープチェーン
もし関数のなかに出てきた名前がCallオブジェクトとグローバルオブジェクトのどちらにもあったらどうなるか?
Callオブジェクトのものが優先されます。
この,変数あるいは関数の名前解決を行う優先順位の仕組みをスコープチェーンといいます。
スコープチェーンは関数の構文構造(関数の処理が書かれているコード)を元に内側の関数から外側の関数そしてグローバルの向きに優先順位が低くなります。
例えば次の場合
var a = 0; function func1() { var a = 100; function func2() { a = -1; return a; } func2(); }
上記のコードでfunc2が実行されたとき,変数aを探す順序は
- func2のCallオブジェクトのプロパティ
- func1のCallオブジェクトのプロパティ
- グローバルオブジェクトのプロパティ
となります。