variable
文は変数を宣言し、任意でそれをある値に初期化します。
構文
var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
varnameN
- 変数名。任意の有効な識別子。
valueN
- 変数の初期値。任意の有効な式。
説明
現れた場所に関係なく、変数の宣言はコードを実行する前に処理されます。var
を伴って宣言した変数のスコープは実行コンテキスト (execution context)であり、これは変数を含んでいる関数、または関数の外で宣言された変数はグローバルになります。
宣言されていない変数への値の代入は、暗黙的にそれをグローバル変数として宣言します(グローバルオブジェクト (global object) のプロパティになります)。宣言した変数と宣言していない変数の違いは以下のとおりです:
1. 宣言した変数は、その変数を宣言した実行コンテキストの内部にあるとみなされます。宣言していない変数は、常にグローバルになります。
function x() { y = 1; // strict モードでは ReferenceError をスローします。 var z = 2; } x(); console.log(y); // "1" を出力します console.log(z); // ReferenceError をスローします。z は x の外部で定義されていません。
2. 宣言した変数は、コードを実行する前に生成されます。宣言していない変数は、変数に代入するコードを実行するまで存在しません。
console.log(a); // ReferenceError をスローします。 console.log('still going...'); // 実行されません。
var a; console.log(a); // ブラウザによって "undefined" または "" を出力 console.log('still going...'); // "still going..." と出力
3. 違いは、宣言した変数は実行コンテキスト (関数またはグローバル) の設定変更不可プロパティになります。宣言していない変数は設定変更可能です (例えば、削除できます)。
var a = 1; b = 2; delete this.a; // strict モードでは TypeError をスローします。そうでなければ静かに失敗します。 delete this.b; console.log(a, b); // ReferenceErrorをスローします。 // プロパティ 'b' は削除されており、存在しません。
これら 3 つの違いにより、変数宣言に失敗し予期しない結果につながる可能性が高いです。結論として、関数スコープかグローバルスコープかにかかわらず、常に変数を宣言することをお勧めします。また、ECMAScript 5の Strict モードでは関数内で宣言していない変数に値を代入するとエラーをスローします。
varの巻き上げ(hoisting)
変数の宣言 (および一般的な宣言) はコードを実行する前に処理されますので、変数はコード内のどこで宣言しても、コードの先頭で宣言したものと等価になります。また、変数を宣言する前に変数を使用することもできます。この動作は、変数の宣言が関数やグローバルのコードの先頭に移動したように見えるため、"巻き上げ (hoisting)" と呼ばれます。
bla = 2 var bla; // ... // 次のように見なされます var bla; bla = 2;
このため、変数は常にスコープ (グローバルのコードまたは関数のコード) の先頭で宣言することをお勧めします。そうすればどの変数が関数スコープ (ローカル) であるか、あるいはスコープチェインによって決定されたものかが明確になります。
例
二つの変数を宣言して初期化する
var a = 0, b = 0;
二つの変数に一つの文字列を代入する
var a = "A"; var b = a; // 以下と等価です var a, b = a = "A";
順番に注意してください:
var x = y, y = 'A'; console.log(x + y); // undefinedA
ここではコードを実行する前に x
と y
が宣言され、そのあとに代入を行います。"x = y
" を実行したとき、y
が存在しますので ReferenceError
は発生せず、値は 'undefined
' になります。よって、x
に undefined 値が代入されます。そして、y
に値 'A' が代入されます。その結果、1 行目の後は x === undefined && y === 'A'
となり、最終結果に至ります。
複数の変数を初期化する
var x = 0; function f(){ var x = y = 1; // x はローカルで宣言されます。y は違います! } f(); console.log(x, y); // 0, 1 // x は想定どおり、グローバル側の変数です。 // しかし、y は関数の外部に漏れ出ています!
暗黙のグローバル変数と関数スコープの外部
暗黙的にグローバルに現れた変数は、関数スコープの外部で参照することができます:
var x = 0; // x はグローバルで宣言して、値 0 を代入 console.log(typeof z); // z はまだ存在していないため、undefined になる function a() { // a を呼び出すと、 var y = 2; // y を関数 a のローカルで宣言して、値 2 を代入 console.log(x, y); // 0 2 function b() { // b を呼び出すと、 x = 3; // グローバルの x に 3 を代入して、新たなグローバル変数は生成しない y = 4; // 外側の y に 4 を代入して、新たなグローバル変数は生成しない z = 5; // 新たなグローバル変数 z を生成して、値 5 を代入 } // (strict モードでは ReferenceError が発生) b(); // b を呼び出すと、グローバル変数として z を生成 console.log(x, y, z); // 3 4 5 } a(); // b も呼び出す console.log(x, z); // 3 5 console.log(typeof y); // y は関数 a のローカル変数であるため、undefined になる
仕様
仕様書 | 策定状況 | コメント |
---|---|---|
ECMAScript 1st Edition (ECMA-262) | 標準 | 最初期の定義。JavaScript 1.0 で実装。 |
ECMAScript 5.1 (ECMA-262) var statement の定義 |
標準 | |
ECMAScript 2015 (6th Edition, ECMA-262) variable statement の定義 |
標準 | |
ECMAScript 2017 Draft (ECMA-262) variable statement の定義 |
ドラフト |
ブラウザ実装状況
機能 | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
基本サポート | (有) | (有) | (有) | (有) | (有) |
機能 | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
基本サポート | (有) | (有) | (有) | (有) | (有) | (有) |