変数の有効範囲
変数
先のプログラムでは、takasa, sankaku, sikaku などの名前を値を覚えるために使っています。 名前と値を対応づけ、値を名前で使う(表す)ことができることを学びました。
このように用いられる名前を、こんどは名前の方に注目して考えてみましょう。 例えば、takasaという名前に対応づけられる値は、5であったり、8であったり、実行のたびに異なります。 takasaの表している値が変化しているように見えます。
このことから、値と対応づけられるもののことを variable (バリアブル、変化するもの)と呼びます。 日本語では変数といいます。
変数の例
先ほどのプログラムを再掲します。
プログラム内で使った名前は
- menseki, yoko, takasa, sankaku, sikaku, wa, dai, syo
の8つです。
menseki は関数の名前です。
yoko は(関数の)引数の名前です。
takasa, sankaku, sikaku, wa, dai, syo が変数にあたります。
引数は変数として扱うこともあります。 function や return は処理系で使い方が決まっている名前です。 Math.sqrt は処理系で用意されている関数の名前です。
変数の値
自分で名前をつけた変数は、いつ使えるのでしょうか。
代入文を使って値と対応づけられた変数は、代入の後で、名前を入力するとその値が表示されました。
js> a = 25; ... js> a 25
まだ一度も値と対応づけられていない名前を参照しようとすると、次のようなエラーが表示されます。
js> boo js: "<stdin>", line 10: uncaught Javascript runtime exception: !ReferenceError: "boo" is not defined.
上のプログラムを
js> load('sample.js');
で読み込んだとします。こうしてプログラムを実行した後では、 使われた変数には最後に対応付けられた値が記憶されています。 例えば、変数 dai の値を表示させることができます。
js> dai 36
変数 yoko, takasa, sankaku, sikaku, syo についても同様に値を記憶していることが確かめられます。 最後に対応づけられた(代入された)値が記憶されています。
変数 wa は数箇所で使われています。どの値を記憶しているのでしょうか? 関数mensekiが呼び出されたときに関数本体内で
- wa = sankaku + sikaku;
により値が代入されます。 関数呼び出しが2回行われてdaiとsyoの値が求まった後に、
- wa = dai+syo;
が行われ、値が代入されます。 実行の順に追いかけてみると、waに対する代入はこれが最後ですから、このときの値を記憶しているのがわかります。
名前の有効範囲
関数の引数である yoko の値はどうでしょうか。 yoko も関数本体の中では、変数と同様に扱われます。
ところが実行後にyokoの値を確認しようとしても
js> yoko js: "<stdin>", line 10: uncaught Javascript runtime exception: !ReferenceError: "yoko" is not defined.
のようにエラーが表示されます。 上で述べた、定義されていない変数を使ったというエラーと同じものです。
引数であるyokoはこの関数の本体の中でしか使えないのです。 このように、使える範囲が限られる名前があります。
ローカル変数
関数内で使う変数は、関数の外からは参照できないようにするのが普通です。
他でどんな名前が使われているか考えなくても済むからです。
上の例の変数 wa のように、関数の中と外とで同じ名前が別の目的で使われると、それがもとでプログラムにバグ(誤り)が入る可能性が大きくなるからです。
関数mensekiは同じ定義だとして、
wa = 3*3*Math.PI + 4*5; haiiro = menseki(3);
のような文があった場合、waの値を先に求めておいても、その後で関数mensekiを呼び出したためにwaの値が別の値に変わってしまいます。
プログラムを書くときに、利用する関数の本体の中でどんな変数(名前)が使われているのかを調べるのはたいへんです。 プログラムが少し大きくなり、関数がいくつも使われるようになると、使われる名前をすべて考えながらプログラムを書くのは困難です。
その関数の外からは参照できないような変数をローカル変数といいます。
ローカル変数の宣言
ローカル変数は関数本体の先頭で宣言します。 宣言は var に続けて変数名をカンマで区切って書き、セミコロンで終わります。
関数mensekiの本体では引数の他に、takasa, sankaku, sikaku, wa の4つの変数を使っていますから、これらをローカル変数として宣言します。 2行目が追加分です。
補足(特殊なケースですが前回の課題で、該当する解答がありました)
関数の名前と同じ名前の変数をその関数内で使った場合にどうなるか。
function menseki ( yoko ) { ... menseki = sankaku + sikaku; ... }
var宣言が行われていない場合、loadを行った後の1回目の実行(呼び出し)はうまくいきますが、再度実行しようとするとエラーになります。
この場合も変数mensekiのvar宣言がされていれば正しく動作します。