変数のスコープ
グローバルスコープ/ローカルスコープ
- var宣言で定義された変数は、その関数内のローカルスコープ
- var宣言なしで定義された変数は、どこで定義されてもグローバルスコープ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
/* グローバル領域での定義 */ v1 = "global1"; var v2 = "global2"; console.log( "start" ); console.log( "v1=" + v1 );// ->"global1" console.log( "v2=" + v2 );// ->"global2" /* グローバル変数の関数内での参照 */ f1(); function f1() { console.log( "in f1()" ); console.log( "v1=" + v1 );// ->"global1" console.log( "v2=" + v2 );// ->"global2" } /* ローカル変数とグローバル変数 ・まずf2()内で同名の変数をローカル定義(var宣言) ・その実行結果は、同名のグローバル変数に影響を与えない ・ローカルで定義された変数はグローバル参照できない */ f2(); console.log( "after f2()" ); console.log( "v1=" + v1 );// ->"global1" console.log( "v2=" + v2 );// ->"global2" //console.log( "v3=" + v3 ); -> error "not defined" function f2() { var v1 = "local1"; var v2 = "local2"; var v3 = "local3"; console.log( "in f2()" ); console.log( "v1=" + v1 );// ->"local1" console.log( "v2=" + v2 );// ->"local2" console.log( "v3=" + v3 );// ->"local3" } /* 関数内でのグローバル変数の影響 ・f3()内でvarなしで定義された変数はグローバル ・既に存在すれば上書きされる(v1, v2) ・存在していなければ新たにグローバル定義される(v3) 以下ではf3()が実行され、その結果でグローバル変数が影響を受ける */ f3(); console.log( "after f3()" ); console.log( "v1=" + v1 );// ->"local1" console.log( "v2=" + v2 );// ->"local2" console.log( "v3=" + v3 );// ->"local3" function f3() { v1 = "local1"; v2 = "local2"; v3 = "local3"; console.log( "in f3()" ); console.log( "v1=" + v1 );// ->"local1" console.log( "v2=" + v2 );// ->"local2" console.log( "v3=" + v3 );// ->"local3" }<br> |
ブロックスコープ
JavaScriptにはブロックスコープの概念はない。
関数の中のif{}やfor{}など複数のブロックで同じ変数名を用いると、関数内で共通の変数になる。
特に、for文のループカウンタなどの一時的な変数は、不用意にvar宣言なしで用いると、予期しないところでグローバルに影響を与えてしまう可能性がある。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* 関数f()を呼び出し、その後の変数をチェック */ f(); console.log( "after f()" ); console.log( "v1=" + v1 );// 関数内のvarなしはグローバル //console.log( "v1=" + v2 ); -> error "not defined" //console.log( "v1=" + v3 ); -> error "not defined" console.log( "v4=" + v4 );// for文でもvarなしはグローバル function f() { console.log( "in f()" ); { v1 = "v1 in block"; var v2 = "v2 in block"; } console.log( "v1=" + v1 ); console.log( "v2=" + v2 ); // for文でvar宣言すれば、関数内ローカルにはなる for ( var v3 = 0; v3 < 2; v3++ ) { console.log( "v3 in for block:" + v3 ); } // ただしブロック内のみのローカルとはならない console.log( "v3 out of for block:" + v3 ); // for文でvarなしで宣言するとグローバル変数になる for ( v4 = 0; v4 < 2; v4++ ) { console.log( "v4 in for block:" + v4 ); } console.log( "v4 out of for block:" + v4 ); } |
関数の引数のスコープ
関数の引数はvarなしで宣言するが、スコープは関数内ローカルとなる。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var n = 1; console.log( f( n ) ); console.log( n ); function f( n ) { console.log( n ); n++; console.log( n ); return n; } |
- グローバル領域でn = 1を定義
- f( n )で引数を引き取った後、関数内ではn == 1
- 関数内でnをインクリメントし、n = 2
- 関数の結果はf( n ) = 2
- その後、グローバル領域でn == 1で変化していない
変数操作のタイミング
グローバル変数への操作は、スクリプトがの実行の際に行われる。htmlファイル内であれば、そのファイルが読み込まれた時。別のjsファイルの場合はそれが読み込まれた時。
ローカル変数への操作は、その関数が実行された時。
以下の例では、htmlファイル読み込み時にグローバル変数が定義・参照され、その後ボタンを押すたびにmain()関数が実行され、ローカル変数が定義・参照される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<input type="button" value="Test" onclick="main()"> <script> var global = "global"; console.log( global ); function main() { var local = "local"; console.log( global ); console.log( local ); } </script> // 実行結果 // global // 以下、ボタンを押すごとに // global // local |