JavaScript のスコープでちょっと驚いた

本読んでて気になったことをばメモってみる.
読んでた本は, オライリーの 初めての JavaScript っての.



まずはスコープに関しての簡単なメモをば.

  • var を使って宣言すれば, スコープは局所になる.
  • var を使わなければ, スコープは大域になる.
  • { ... } 内で宣言された変数は, そのブロックを越えたスコープを持つ.

気になったのは, 3番目の.
うちは, よく, C言語なんかだと, for ループのカウンタ用の変数を作るとき,

    {
        int i = 0;
        for( i=0; i<3; i++ ){
            printf( "hoge\n" );
        }
    }

のような書き方をするから.
理由は, カウンタ用の変数を for の直前で書きたいってのとか,
プログラム書いてて, ループを書こう思たときに, 関数の頭まで戻って i とか j を宣言するのが嫌だから.


んで, 気になったから実験してみた.
まず, C 言語バージョン.
使ったコンパイラは, gcc version 4.1.2 20061115 (prerelease) (Debian 4.1.1-21).

#include <stdio.h>

int main( int argc, char *argv[] )
{
    int foo = 3;

    printf( "foo : %d\n", foo ); /* value is 3. */

    {
        int foo = 9;
        int bar = 6;
        printf( "foo : %d\n", foo ); /* value is 9 */
        printf( "bar : %d\n", bar ); /* value is 6 */
    }

    printf( "foo : %d\n", foo ); /* value is 3. */
//    printf( "bar : %d\n", bar );      /* error! */

    return 0;
}

結果は, 3, 9, 6, 3. になる.
一番最後の bar は, { ... } の中で宣言されたものだから,
コメントアウトを外すとそんな変数宣言されてねーぜとエラーになる.



次に JavaScript.
使った処理系は, SpiderMonkey 1.6.1 2007-04-01

// test of { ... } scope.

var foo = "hoge";
print( "foo : " + foo );        // is hoge.

{
    var foo = "hogepiyo";
    var bar = "piyo";
    print( "foo : " + foo );    // is hogepiyo.
    print( "bar : " + bar );    // is piyo.
}

print( "foo : " + foo );        // foo is not "hoge". is hogepiyo.
print( "bar : " + bar );        // not error! is piyo.

(function(){
    var foo = "hage";
    print( "foo : " + foo );    // is hage.
})();

print( "foo : " + foo );        // is hogepiyo.

// scope.js ends here

こんな感じ.
{ ... } の中で宣言した foo とか bar が, { ... } の外でも有効になってる.
ちょっと, いや, かなりビックリした. これは, ... ハマるところだったかもしれない.
ちなみに, C言語と同様の動作をさせたければ,
ブックマークレットを書くやり方で, (function(){ ... })() と書けば大丈夫みたい.
ちょっと記述量が多いかなという気もせんでもないけど, まあ, しょうがないか.

更新時刻

2007年, 9月23日, 23:36