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