"var"の機能について、以下の"ディノオープンラボ"でサンプルと共に解説されていたので、試してみる。
無名関数と関数リテラルについては置いておいて、単純なStringオブジェクトで試してみます。
baz = 'abc'; function(){ alert(baz); // (1) alerts 'undefined' var baz = 'def'; alert(baz); // (2) alerts 'def' }(); alert(baz); // (3) alerts 'abc'
関数コードの中でvarを使うと、実行スコープにundefinedでbazという識別子が登録されます。
ですので(1)のalert()ではundefinedになります。(2)のalert()時点で、関数の実行スコープのbazには 'def' という値が入ってますので、それがalert()で表示されます。
(3)のalert()ですが、(1) - (2) で参照されているbazはあくまでも無名関数による実行スコープに登録されたものであって、グローバルスコープのbazは弄ってません。なので、最初に設定していた 'abc' がそのままalert()で表示されます。
で、試しに関数の中の var を取ってみます。
baz = 'abc'; function(){ alert(baz); // (1) alerts 'abc' baz = 'def'; alert(baz); // (2) alerts 'def' }(); alert(baz); // (3) alerts 'def'
こうすると関数コード中もグローバルスコープのbazを参照するようになるので、(3)でも変更後の値 'def' がalert()表示されます。
ちなみに実行スコープにより分断されるのは関数コードだけであって、一般的なBlock構文では実行スコープは生成されません。
foo = 'ABC'; { alert(foo); // (1) alerts 'ABC' var foo = 'DEF'; alert(foo); // (2) alerts 'DEF' } alert(foo); // (3) alerts 'DEF'
これについてはECMA262に記述されています。
12.2 Variable statement
...
A Block does not define a new execution scope.
Only Program and FunctionDeclaration produce a new scope.
Variables are initialised to undefined when created.