第11話:変数のスコープ

第1部 JavaScriptプログラミングの基本

目次

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ

マンガ台詞

【1Page】
アイコン先生:前回は 『関数』について 説明した
    『関数』を使った プログラムでは 関数内に入ったり 出たりして処理が 進んでいた
    実はこの 『関数』の内と外で 『世界』が違うんだ
        【外】
        function kannsuu() {
            【内】
        }
        【外】
アイコンアイコンアイコン3人:世界?
アイコン先生:そうだ 括弧の中では ローカル ルールが 適用される
アイコン遊:ローカル ルールって 地方ルールってこと?
アイコン先生:ああ
【2Page】
アイコン遊:守のお弁当を 私が食べていいみたいな
    教室内で決まっている ルールのこと?
アイコン守:(げんなり)
アイコン先生:あーまあ そういうことだ
アイコン先生:じゃあ詳しく 説明するぞ
    プログラム全体が 学校なら
    『関数』内は 教室の中の ようなものだ
        『プログラム全体=学校』
        function kyousitu() {
            『関数の中=教室の中』
        }
    『var ~』と 作った変数は その『関数』の 内側だけで 有効になる
    これを 『スコープ』と言う
アイコンアイコンアイコン3人:ぽかーん
【3Page】
アイコン先生:ちょっと 難しいかな
    図を描いて 説明しよう
    (各変数の有効範囲を矢印で図示)
        プログラム全体(巨大な関数と想定)
            var globalA;
            内側で有効 globalAは有効
            function funcIn () {
                var localA;
            内側で有効 localAはここでのみ有効
            内側で有効 globalAはここでも有効
            }
            内側で有効 globalAは有効
        プログラムの終了
    何か質問は あるか?
アイコン守:こんな感じに 同じ名前の変数があったら どうなるんですか?
        【質問1】
        var a = 10;
        alert(a);
        showLocal();
        alert(a);

        function showLocal() {
            var a = 5;
            alert(a);
        }

        【質問2】
        for (var i = 0; i < 10; i ++) {
            document.write(i + " / "
                + calc(i) + "<br>");
        }
        function calc(arg) {
            var result = "";
            for (var i = 0; i < arg; i ++) {
                result += i + ",";
            }
            return result;
        }
【4Page】
アイコン先生:同じ名前の変数が あった場合は ローカルな 変数が優先される
    質問1は 『10』『5』『10』と 表示される
    2、4行目は グローバルで『10』
    3行目はローカルの 『5』が使われる
        var a = 10;
        alert(a);       『10』
        showLocal();
        alert(a);       『10』

        function showLocal() {
            var a = 5;
            alert(a);   『5』
        }
    質問2の場合は 最初の『for』文の『i』と
    『関数』内の『for』文の『i』が 独立して実行される
        for (var i = 0; i < 10; i ++) {
            document.write(i + " / "
                + calc(i) + "<br>");  『0,1,2,…』
        }
        function calc(arg) {
            var result = "";
            for (var i = 0; i < arg; i ++) {
                result += i + ",";      『0,1,2,…』
            }
            return result;
        }
    結果は 『
        0 / 
        1 / 0,
        2 / 0,1,
        3 / 0,1,2,
        4 / 0,1,2,3,
        5 / 0,1,2,3,4,
        6 / 0,1,2,3,4,5,
        7 / 0,1,2,3,4,5,6,
        8 / 0,1,2,3,4,5,6,7,
        9 / 0,1,2,3,4,5,6,7,8,
    』 と表示される
【5Page】
アイコン遊:この 変数の『スコープ』? は何か意味があるの?
    私には少し難し すぎるん だけど
アイコン先生:短いプログラムを 書く場合には関係ないが
    長いプログラムを 書く場合には重要になる
    用語としては 括弧の中で使う変数を 『ローカル変数』
    プログラム全体で使う変数を 『グローバル変数』 と呼ぶ
アイコン遊:グローバル!
    世界に羽ばたく 私みたいな変数ね!
アイコン麗:んっ あなたは 海外旅行も行ったことのない
    ローカルな人間 でしょう
アイコン遊:くっ この嫌味な ブルジョア女め~!

説明

この章では、『変数のスコープ』について学びます。『変数のスコープ』は、『関数』を使ったプログラムを書く上で、非常に重要な考え方になります。

『関数』は、プログラムの様々な場所から呼び出されます。また、『関数』から『関数』を呼び出したりなど、複雑な入れ子構造を持ったりします。そういった際、同じ名前の変数があったら、どうなるのでしょうか?

たとえば、ループ処理の実行回数を数える時によく使う『i』という名前の変数。この変数『i』を、プログラムのいろんな場所に書いていたとします。『関数』の中にも外にも書いたとします。

『関数』に入って、出てきた時点で、この変数『i』の値が、勝手に書き変わっていたとしたらどうなるでしょうか? ループが正常に終了せず、場合によっては無限ループになる可能性もあります。

そういった問題を解決するために、JavaScriptでは『変数のスコープ』という概念を導入しています。

それでは以下、『変数のスコープ』について詳しく説明していきます。

『変数のスコープ』

JavaScriptのプログラムでは、『関数』の内側の領域は、外側の領域とは違う空間になっています。そして、『関数』の外側の通常の場所を『グローバル』と呼び、『関数』の内側になる場所を『ローカル』と呼びます。また、『グローバル』で宣言された変数を『グローバル変数』、『ローカル』で宣言された変数を『ローカル変数』と呼びます。

【グローバルな領域】
var globalVar = 1;        // グローバル変数

function kansuu() {
    【ローカルな領域】
    var loclalVar = 0;    // ローカル変数
}
【グローバルな領域】
var globalVar2 = 2;       // グローバル変数

『ローカル』な領域では、ローカルルールが適用されます。このローカル ルールは、『ローカルで宣言された変数は、その領域内のみで有効』というものです。また、『グローバル』な領域と『ローカル』な領域に、同じ名前の変数があった場合は、『ローカル』な領域の変数の方が優先されます。

このように、変数にはそれぞれ有効範囲があります。この変数の有効範囲のことを、『変数のスコープ』と言います。

動作例

以下、実際の動作例を示します。

var a = 10;
alert(a);       // グローバル変数『a』の値『10』が表示される
showLocal();    // 『showLocal』関数が呼び出され、
                // ローカル変数『a』の値『5』が表示される
alert(a);       // グローバル変数『a』の値『10』が表示される

function showLocal() {
    var a = 5;
    alert(a);   // グローバル変数『a』ではなく、
                // ローカル変数『a』の値『5』が表示される
}

【結果】

10
5
10

最初の『alert』では、『グローバル変数』である『a』の値『10』が表示されます。次の『showLocal』内の『alert』では、『ローカル変数』である『a』の値『5』が表示されます。最後の『alert』では、『グローバル変数』である『a』の値『10』が表示されます。

複雑な処理の場合

このルールは、複雑な処理になっても、同じように適用されます。

for (var i = 0; i < 10; i ++) {
    document.write(i + " / " + calc(i) + "<br>");
        // グローバル変数『i』の値が『0,1,2,…』と出力される
        // その際、『calc』関数の戻り値も連結して出力される
}
function calc(arg) {
    // グローバル変数『i』の値を、引数『arg』として受け取っている
    var result = "";
    for (var i = 0; i < arg; i ++) {
        // ローカル変数『i』が、『0』から『arg』未満の間、処理を行う
        result += i + ",";
        // ローカル変数『i』の値『0,1,2,…』が連結されて
        // 戻り値として利用される
    }
    return result;
}

このプログラムを実行した結果は、以下のようになります。

【結果】

0 / 
1 / 0,
2 / 0,1,
3 / 0,1,2,
4 / 0,1,2,3,
5 / 0,1,2,3,4,
6 / 0,1,2,3,4,5,
7 / 0,1,2,3,4,5,6,
8 / 0,1,2,3,4,5,6,7,
9 / 0,1,2,3,4,5,6,7,8,

最初の『for』文内の『i』と、『calc』関数内の『for』文の『i』は、『変数のスコープ』が異なるので、独立しています。

そのため、『calc』関数内で『i』の値が書き換わっても、最初の『for』文内の『i』の値は書き換わりません。

参考

サンプルの入手

以下は、今回出てきたサンプルです。

ZIPでまとめてダウンロード (右クリックから保存してください)

sample1.html』(守の質問1)を表示

sample1b.html』(守の質問2)を表示

プログラムの中身を見たい場合は、それぞれのHTMLファイルをブラウザで開いたあと、右クリックをして『ソースの表示』を選択してください。

メモ帳で、ファイルの中身を見ることができます。