変数の宣言とエラー

今回はJavaScript 第6版』David Flanagan (著),    村上 列 (翻訳)  から予約語、var の省略、値の代入前の変数の参照、変数の上書きなど初歩的なJavaScript の挙動について抜粋しました。(var の語源はvariableからだそうです。)

2.4.1 予約語
JavaScript には予約語がたくさんあります。以下に挙げるような単語は、プログラム中で識別子として使うことはできません。

break delete function return typeof
case do if switch var
catch else in this void
continue false instanceof throw while
debugger finally new true with
default for null try

さらに、以下の単語は、通常のJavaScriptコードでは識別子として使えますが、strictモードの場合は予約語として扱われ識別子には使えません。

implement let private public yield
interface package protected static

JavaScript には、たくさんのグローバル変数や関数があらかじめ定義されています。以下のような定義済みのグローバル変数やグローバル関数と同じ名前を識別子に使うことは避けた方が無難です。

argument encodeURI Infinity Number RegExp
Array encodeURIComponent isFinite Object String
Boolean Error isNaN parseFloat SyntaxError
Date eval JSON parseInt TypeError
decodeURI EvalError Math RangeError undefined
decodeURIComponent function NaN ReferenceError URIError

3.9 変数の宣言

JavaScript で変数の宣言をするには、キーワード var を使います。

var i;
var sum;

複数の変数をカンマ(,)で区切って宣言することもできます。

var i, sum;

for ループやfor/in ループでvar 文を記述することで、ループの一部としてループ変数を宣言することもできます。

for (var i = 0; i < 10; i++) {
  var sum += i;
}
return sum;

もしvar 文で変数の初期値を設定しなかった場合は、宣言された変数は、何か値が代入されるまで undefined(未定義値)になります。

3.9.1 宣言の繰り返しと省略

var 文で宣言されていない変数から値を読みだした場合は、エラーになります。ECMAScript 5 の strict モードでは、宣言されていない変数に対して値を代入してもエラーになります。しかし、歴史的には、つまり非 strict モードでは、宣言されていない変数に対して値を代入した場合、JavaScript はグローバルオブジェクトのプロパティとして変数を作成します。ただし、完全に同じというわけではありません。~(中略)~ つまり、グローバル変数を宣言しなくても問題ないということです。ただし、このようなプログラミングスタイルは決してよいものとは言えません。変数は var を使って宣言するようにしてください。

3.10 変数のスコープ

プログラムのソースコード中における変数の有効範囲をスコープといいます。グローバル変数のスコープは、プログラム全体です。ローカル変数のスコープは、その変数が宣言された関数の中だけに限定されます。関数の中にグローバル変数と同じ名前のローカル変数があった場合は、ローカル変数が優先されます。つまり、グローバル変数と同じ名前でローカル変数や仮引数を宣言すると、グローバル変数が隠されます。

var scope ="global";          // グローバル変数を宣言する。
function checkscope() {
  var scope = "local";        // 同じ名前でローカル変数を宣言する。
  return scope;          // ローカル変数の値が返される。
}
checkscope()                  // => "local"
scope = "global";        // var 文を省略してグローバル変数を宣言する。
function checkscope2() {
  scope = "local";   // あれ!これはグローバル変数を変更したことになる。
  myscope = "local"; // 代入で新たなグローバル変数が暗黙的に宣言。      
  return { scope, myscope }    // 2つの値を返す。
}
checkscope2()                // => {"local","local"}
scope                        // => "local": グローバル変数が変更された。
myscope                // => "local": グローバルな名前空間に追加された。

4.13 関数の定義方法(宣言、式、もしくはコンストラクタ)

// 関数コンストラクタ:最後のパラメータには関数のロジック(関数本体)が入る

var addConstructor = new Function('x',  'y', 'return x + y');

// 関数宣言(function 文)

function addStatement(x, y) {
  return x + y;
}

// 関数式

var addExpression = function(x, y) {
  return x + y;
};

次の例では、foo プロパティをグローバルオブジェクトに格納し、異なるスコープからfoo プロパティにアクセスします。

var foo = 'bar';  // foo はグローバルオブジェクト直下に格納されたグローバル変数
var myApp = function() {  // 関数はスコープを作ることを思い出して
  var run = function() {
    alert(foo);  // 出力: 'bar'
}();
}
myApp();