var

変数の宣言を行い、任意で値を初期化します。

文法

var varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
//実際には次のように書かれます。
var varname1;                   //変数の宣言のみ
var varname2 = 2;               //変数の宣言と初期化
var varname3 = 3, vaname4 = 4;  //カンマ区切りで複数の変数を宣言
varnameN
変数名を指定します。 有効な識別子を任意に指定することが可能です。
valueN
変数の初期値を指定します。 有効な式を任意に指定することが可能です。

説明

変数の宣言は、それが何処で行われていようとも、コードの実行が行われる前に処理されます。 varによる変数宣言のスコープは、それを囲んでいる関数、 または、いずれかの関数の外で変数宣言がされていればグローバル空間の、どちらかの現実行コンテキストになります。

宣言されていない変数に値を割り当てると、割り当てが実行された際に、 暗黙的にグローバル変数(グローバルオブジェクトのプロパティになります)として作成されます。 宣言された変数、宣言されていない変数の違いは下記の通りです。

  1. 宣言された変数は、それが宣言された実行コンテキスト内でのみ有効です。 宣言されていない変数は、常にグローバルになります。

    function x() {
      y = 1;   // strictモードであれば、ReferenceErrorがスローされます
      var z = 2;
    }
    
    x();
    
    console.log(y); // "1"を出力
    console.log(z); // zはx関数の外部で宣言されていないため、
                    // ReferenceErrorがスローされます。
    
  2. 宣言された変数は、コードが実行される前に作成されます。 宣言されていない変数は、それに変数が割り当てるコードが実行されるまで存在しないことになります。

    console.log(a);                // ReferenceErrorをスロー
    console.log('still going...'); // 実行されません。
    
    var a;
    console.log(a);                // "undefined"または""を出力(ブラウザに依存)
    console.log('still going...'); // "still going..."を出力
    
  3. 宣言された変数は、その実行コンテキスト(関数またはグローバル)での設定不可プロパティになります。 宣言されていない変数は設定可能です。(例えば、削除(delete)することが出来ます。)

    var a = 1;
    b = 2;
    
    delete this.a; // strictモードでTypeErrorをスローし、そうでなければ静かに失敗します。
    delete this.b;
    
    console.log(a, b); // ReferenceErrorがスローされます。
    // 'b'プロパティは削除されており、この時点では存在しません。
    

これら3つの違いから、変数宣言のミスは思いもよらない結果を導くことになりかねません。 そのため、関数、グローバル変数内に関係無く、変数宣言を常に行うことが推奨されています。 またECMAScript 5のstrictモードでは、未定義の変数への割り当てを行うと、エラーがスローされます。

varの巻き上げ(var hoisting)

変数宣言(一般的にあらゆる宣言は)はコードが実行される前に処理されるため、 コード内の何処かで行われた変数宣言は、先頭で宣言されたことと同じことになります。 これは、その宣言が行われる前に、変数を使用する事が出来る事を意味します。 この挙動は、関数またはグローバルのコードの先頭に変数宣言が移動されるものとして、"巻き上げ"(hoisting)と呼ばれます。

bla = 2
var bla;
// ...

// 暗黙的に、下記のように解釈されます。

var bla;
bla = 2;

このような理由から、そのスコープの先頭(グローバルコードの先頭、関数コードの先頭)で変数の宣言を常に行うことが推奨されており、 そのようにすることで変数が関数のスコープであること、スコープチェーン内で解決されることが明確なります。

2つの変数の宣言と初期化

var a = 0, b = 0;

2つの変数へ1つの文字列値を割り当て

var a = "A";
var b = a;

// 下記と同義です

var a, b = a = "A";

順番に注意してください。

var x = y, y = 'A';
console.log(x + y); // "undefinedA"が出力

ここで、xyはコードが実行される前に宣言され、その後に割り当てが行われます。 "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();                   // aの呼び出しは、bも呼び出します。
console.log(x, z);     // 3 5 を出力
console.log(typeof y); // 関数aのローカルであるため、yは未定義(undefined)となります。

仕様

ブラウザ互換性

デスクトップ
機能 Chrome Firefox
(Gecko)
IE Opera Safari
基本
モバイル
機能 Android Chrome for
Android
Firefox
Mobile
IE
Mobile
Opera
Mobile
Safari
Mobile
基本

関連項目

 Back to top

© 2017 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.

このページは、ページトップのURL先のMozilla Developer Network(以下、MDN)のコンテンツを翻訳した内容を基に構成されています。 構成について異なる点も含まれますので、下記の項目を確認し、必要に応じて元のコンテンツをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • 特定のブラウザに特化しすぎている情報やあまりにも古い情報、 または試験的に導入されているようなAPIや機能については、省略していることがあります。
  • 例やデモについて、実際にページ内で動作させる関係で一部ソースコードを変更している場合や、 その例で使用しているコンテンツの単語や文章などを日本人向けに変更しいてる場合があります。
  • MDNの更新頻度が高いため、元のコンテンツと比べ情報が古くなっている可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報の追記を行っている事があります。