JavaScriptにおける変数のスコープ

JavaScriptのスコープはCやC++と少し違う.

変数のスコープ

次のようなプログラムを考えてみる.

var a;
b = 'b:global';
function f() {
    a = 'a':global;
    var c = 'c:local';
    d = 'd:global';
}

f();

document.write(a); // a:globalが出力される
document.write(b); // b:globalが出力される
document.write(c); // undefinedが出力される
document.write(d); // d:globalが出力される

関数外で宣言したvar aは,グローバル変数と見なされる.そのため,f()関数内でa = 'a:global'とすると,グローバル変数aの中身がa:globalに変更される.

b = 'b:global'はvar b = 'b:global'と等価である.varを用いなくとも,変数は暗黙的に宣言される.

関数内でvar c;と変数を宣言した場合,その変数は関数内のみで有効なローカル変数となる.そのため,関数外でdocument.write(c);とするとundefinedが出力される.

関数内でvarを使わずに変数を用いた場合,その変数は暗黙的にグローバル変数として宣言される.

すなわち,

function f() {
    foo = 0;
}

は,

var foo;
function f() {
    foo = 0;
}

と同じである.

ローカル変数のスコープ

次に,次のようなプログラムを考えてみる.

var foo = 'global';

function f() {
    document.write(foo); // undefinedが出力される

    var foo = 'local';
    document.write(foo); // localが出力される
}

document.write(foo); // globalが出力される

関数内で定義したvar fooはグローバル変数のfooを隠す.また,JavaScriptでは,ローカル変数のスコープは関数全体であるため,f()関数内でのdocument.write(foo)はundefinedを出力する.

このプログラムは次と等価である.

var foo = 'global';

function f() {
    var bar;

    document.write(bar);

    bar = 'local';
    document.write(bar);
}

document.write(foo);

ブロックと変数のスコープ

C言語の場合,ローカル変数のスコープはブロック単位である.

void func()
{
    int foo = 0;
    {
        int bar = 1;
        printf("%d\n", foo); // 0が出力される
        printf("%d\n", bar); // 1が出力される
    }

    printf("%d\n", foo); // 0が出力される
    printf("%d\n", bar); // エラー.barは未定義の変数
}

JavaScriptの場合,ローカル変数のスコープはブロック単位ではなく関数単位であるので注意が必要である.

function f() {
    var foo = 0;
    {
        var bar = 1;
        doument.write(foo); // 0が出力される
        doument.write(bar); // 1が出力される
    }

    doument.write(foo); // 0が出力される
    doument.write(bar); // 1が出力される
}