スコープ
スコープ(有効範囲)とは、その変数の見える範囲です。スコープが必要な理由は、他の人がつけた名前が、そのプログラムを利用する人にまで悪影響がでてしまったり、関数を宣言するとき使う引数名に他の関数と同じ名前が使えなくなるなどの状況が発生します。
これだけでは、要点はつかみにくいと思います。しかし、スコープを簡単に説明することはなかなか難しいので、厳密な説明は後にします。ここでは、いくつかの前提をおいて説明します。
let と const しか使わない。
'use strict' のストリクトモードしか使わない
JavaScriptには、var, let, constの3つの宣言がありますが、私にはvarは使う必要が感じませんので、ここでは宣言はすべてletかconstで行うことにします。また、ストリクトモードを基本とすることで、宣言せずに変数の使用をすることができなくなるので、'use strict'を使うことにします。これで説明が非常に楽になります。
最初に、const と let の違いは値を再代入(変更)できるかどうかです。つまり、constで変数を定義すると、それ以降変更はできません。つまり、その値は常に変わらないということでプログラムを作成でき、エラーの要因が減少します。
上記の前提のもとでは、宣言した変数のスコープは、そのブロックの中のその場所以降に限られます。宣言したブロックとその内側のブロックでは、その変数のスコープは有効ですが、それ以外では無効となり、その変数は隠されます。(インデントの重要性は個々にもあります。)例えば、関数の引数に使った変数名は、その関数のブロック内のみで有効で、他の関数でも同じ引数名を使ってもなんの影響も与えません。
複数の関数で同じ変数を使いたいときは、関数の外側で(つまり、プログラム初頭)宣言すると、その同じブロック定義したすべての関数でその変数が使えます。つまり外側で宣言した変数は、グローバルスコープ(どこでも見える)となります。
では、例えば同じ名前で、外側とdraw()関数の中で変数宣言をした場合はどうなるでしょうか。次の例では、sameNameが4行目とdraw()の1行目で同じ名前で宣言されています。また、console.log(' xxxx ',sameName);が3箇所にあります。これを実行するとどうなるでしょうか。sameNameは外側で使われているので、すべての領域で使えるはずです。しかし、draw()の中には同じ名前sameName=20;で宣言されているので、draw()関数の中では、そこで宣言されたsameName変数しかスコープが有効ではありません。console.logの出力もそうなると思います。外側で宣言されたsameNameは見えず、20と表示されるはずです。
このように、内側のブロックで宣言された場合は、内側のみで有効かつ同じ名前の外側で宣言された変数はスコープの範囲外になります。同じ名前の変数を使うときは注意してください。
code:scope.js
'use strict'
let a;
let b,c;
let sameName=0;
console.log('外側 ',sameName)
function setup(){
createCanvas(400,400);
a=0;
b=100;
c='red'
background(c)
console.log('in setup ',sameName)
}
function draw(){
let sameName=20;
background(c);
rect(a,b,100,200);
a+=10; a %= width;
console.log('in draw ',sameName)
}
参考:
上記のプログラムで、2行目の let a; を消したら(コメントにしたら)どうなるでしょうか。
ReferenceError: a is not defined
at setup (/sketch.js:8:4)
のように、aが定義されていないとエラーメッセージが表示されます。このように、strictモードでは宣言していない変数は使えません。
では、'use strict' を消したら(コメントにしたら)どうなるでしょうか。
これはエラーも出さずに、普通に動きます。これはどういうことかというと、 じつは宣言なしに使われた変数は グローバルのスコープとなって、setup()関数で初めて出てきたにも関わらず、その外側にあるdraw()関数の中でもその変数は有効になっていると言うことです。もちろん、setup()関数にある a=0 を let a=0;に変えるとstrictモードでなくてもエラーが出ます。aはsetup()関数の中では有効ですが、draw()関数ではスコープ外となります。