var varname1 [= value1] [, varname2 [= value2] ... [, varnameN [= valueN]]];Syntax - var - JavaScript | MDN
var a = 1, b = 2;
同一の値で初期化するならば、
var a = 1, b = 1;
次のようにも記述できます。
var a, b = a = 1;Examples - var - JavaScript | MDN
オブジェクトのプロパティならば、in演算子でその存在を確認できます。またグローバル変数でも、それがWindowオブジェクトのプロパティとなることを利用して、同様に
'a' in window;
とすることで宣言を確認できます。なお、このとき変数名は文字列で指定することに注意します。
関数内でvar文を使用して宣言する以外、すべてグローバル変数となります。関数外で使用する変数がグローバル変数となることを避けるには、匿名関数の中で変数を宣言します。
var a = 0; // グローバル変数 b = 0; // グローバル変数 function Func() { var c = 0; // ローカル変数 d = 0; // グローバル変数 }
ローカルかグローバルかを明確にするために、変数の宣言では必ずvar文を使用します。
ところでクライアントサイドJavaScriptならば、var文を用いず宣言されたグローバル変数はWindowオブジェクトのプロパティとなります。
var文で変数を宣言すると、その宣言より先に変数が参照された場合でも、先に宣言されているものと解釈されます。これを「varの巻き上げ」と呼びます。varの巻き上げ(hoisting) - var - JavaScript | MDN
var | 先に宣言 | 後で宣言 |
---|---|---|
あり |
{ var a = 1; alert( a ); // 1 }問題なし |
{
alert( a ); // undefined
var a = 1;
}
宣言より先に参照しているが、未定義値、つまり宣言はされているが初期化されていないと解釈されている。 |
なし |
{
a = 1;
alert( a ); // 1
}
問題なし
|
{
alert( a ); // ReferenceError: a is not defined
a = 1;
}
varを付けずに宣言して、その宣言より先に参照すると、ReferenceError、つまり宣言されていないと解釈されている。
|
このように宣言前に参照すると特殊な挙動を示すため、つねに先に宣言するようにします。
変数の宣言時に初期化されないとき、値が設定されるまでは未定義の状態となります。
var a; // 初期化していない var b = 0; // 初期化している a = 0; // ここまで未定義 (undefined)
未定義値は、
typeof a === 'undefined'
のようにtypeof演算子の戻り値で判定できます。次のような判定方法もあるようですが、これらの方法では宣言すらされていないと例外が発生します。
a === undefined
a === void 0
!a
a == null
一方でオブジェクトのプロパティが定義されているかどうかは、in演算子で判定できます。
変数の状態 | 操作 | 結果 | |
---|---|---|---|
宣言 | 代入 | ||
宣言されていない (未宣言) |
値が設定されていない | 読み込み | 例外が発生
(ReferenceError: x is not defined) |
代入 | グローバルな変数の宣言となる | ||
宣言されている | 値が設定されていない (未定義) |
読み込み | 未定義 (undefined) が返される |
値が設定されている | 代入 | 問題なく代入される |
たとえば次のようになります。
x = y; // ReferenceError: y is not defined var a; var b = 1; // b==1となる (関数内ならば、ローカル スコープ) c = 1; // c==1となる (グローバル スコープ) x = a; // undefined x = b; // x==1となる
一方でオブジェクトのプロパティの場合は、次のようになります。
var obj = { a: 1 }; x = obj.a; // x==1となる x = obj.b; // undefined x = obj.a.b; // undefined x = obj.b.b; // TypeError: obj.b is undefined obj.b = 1; // obj.b==1となるTypeError - JavaScript | MDN
種類 | スコープの範囲 |
---|---|
グローバル変数 | プログラム全体 |
ローカル変数 | 変数が宣言された関数の中だけ |
関数の仮引数 | その関数の中だけ |
関数内で宣言された変数は、どのブロックで宣言されたかにかかわらず関数全体で有効となります。
function Func( x ) { if( x ) { var a = 256; } for( var b = 0; b < 10; b++ ) { } alert( a ); // aは有効だが、xの値によってはundefinedの場合もある alert( b ); // bは有効で、つねに10 }
JavaScriptには、ブロックレベルのスコープはありません。ただしlet演算子を使える環境ならば、ブロックレベルのスコープを実現できます。
スコープをブロックレベルに制限して、変数を宣言できます。
<script type="application/javascript;version=1.7"> { var a = 1; let b = 1; } alert( a ); // 1 alert( b ); // ReferenceError: b is not defined </script>let - JavaScript | MDN
let演算子はJavaScript 1.7以降でサポートされるため、HTML文書中のscript要素では
<script type="application/javascript;version=1.7">
のように、1.7以降のバージョンを明示する必要があります。さもなくばSyntaxErrorとなります。一方でXULではこのような配慮は不要です。Summary - let - JavaScript | MDN
そもそもletをサポートしないブラウザではこのようなバージョンの記述は無意味で、そのようなブラウザを対象とするならばletの使用を断念します。Browser compatibility - let - JavaScript | MDN
関数内で宣言された変数は、その関数全体で有効であるという定義のために、宣言する場所にかかわらず有効です。しかし初期化されるのは、それが実行された場所になります。
function Func() { var a = 1; alert( a ); // aは有効で、1を出力 alert( b ); // bは有効だが、undefinedを出力 alert( c ); // cは無効で、例外が発生 var b = 1; }
宣言する前に実行されることがないように、変数は関数の先頭で宣言するようにします。
alert( a ); // 初期化前: undefined と表示 var a = 1; alert( a ); // 初期化後: 1 と表示 alert( b ); // 初期化前 (varなしで宣言): エラー発生 (ReferenceError: b is not defined) b = 1;
constキーワードを使用することで、定数を宣言することができます。定数 - Values, variables, and literals - JavaScript | MDN
const PI = 3.14;
※Internet Explorer 11より前は、constキーワードに対応していません。Browser compatibility - const - JavaScript | MDN
constで宣言した定数に新たな値を上書きしようとしても、その値は無視されます。
const a = 1;
a = 2;
alert( a ); // 1と表示
また同名の変数を宣言して上書きしようとすると、例外が発生します。
const a = 1;
const a = 2; // TypeError: redeclaration of const a