JavaScript の var についての考察

Web/JS part.4 で「変数宣言で var を付けないとどうなるのか」といった質問が出ていたので調べつつ考察してみました。

(フォローアップ講習会参加の方々には現在の講習内容を逸脱しますが、そのうち詳しくフォローして行きます。)

var は明示的に変数を宣言するためのステートメントです。
関数のボディ内部にステートメントがある場合、その関数に対するローカルスコープを持つ変数を宣言した事になります。
それ以外の場合は、グローバルオブジェクトのメンバ変数になります。
また var で宣言したプロパティは DontDelete 属性を持ち、従って delete 演算子で削除出来ません(”delete operand” が false を返す)。

もう一つポイントになるのが関数評価の仕組みです。

function() {
	console.log('---');
	var foo = 1;
};

というコードがあった場合、内部解釈的に見ると(インタプリタの挙動に解釈すると)下記のようになります。

function() {
	var foo;
	console.log('---');
	foo = 1;
};

まず var foo; と変数を宣言した後に値を代入しています。

var 無し変数の場合、インタプリタが暗示的に変数をグローバルオブジェクトのプロパティとして確保します。

以上を踏まえて色々遊んでみましょう。

まず var 無しの場合。

bar = "global bar";
console.log(window['bar']);
window.foo = "window foo";
(function() {
	console.log(foo);
})();

ブラウザ環境上の JavaScript ではグローバルオブジェクトは window です。
var 無し
という事で実行結果は

global bar
window bar

となります。

次に var で宣言した場合。

var foo = 1;
console.log(foo);
(function() {
	var foo = 2;
	console.log(foo);
})();
console.log(foo);

実行結果は

1
2
1

関数内で宣言された var ステートメントは関数に対してローカルスコープになります。

次に関数内での挙動を比較。

var foo = 1;
(function() {
	console.log(foo);
	var foo = 2;
})();

インタプリタの解釈では console.log 実行の前に関数内で var foo; が宣言されているので結果は

undefined

undeclared でなく undefined である事に注意。

試しにこうしてみると

(function() {
	console.log(foo);
})();
foo is not defined

となります。

と、説明は付いていると思いますが、間違い、不適切な表現があればご指摘ください。

実際は常に var を付けておく、で決まりだと思います。

ついでに delete の何が嬉しいのか、DontDelete 属性があると何が嬉しいのか、ちっとも分かっていません。教えてくれる人、plz!

追記:
はてブでコメントを頂きました。

    javasript deleteはオブジェクトのプロパティを削除するのに使うので、そのうれしさがあるんでないでしょか。a in obj とかで有無判定するような処理とか。

「a in obj とかで有無判定」でなるほど、と腑に落ちました。gotin さん多謝です!

コメント / トラックバック 1 件

#1 Web/JS(甘口) part.2 - 変数宣言、関数、無名関数 2008/11/28 16:27

[...] 講習会中に代入、代入と言っていますが「束縛の方が適切じゃねぇ?」との指摘を受けました。添付資料の方は「束縛」に修正してあります。 変数宣言で var を付けないとどうなるかのお話も、興味の有る方はご覧下さい。 [...]

コメントする