グローバルスコープとローカルスコープしかない
Jsには2種類のスコープしかない。グローバルスコープ内で宣言した変数をグローバル変数、ローカルスコープ内で宣言した変数をローカル変数という。
- スクリプト全体(トップレベル)で有効なグローバル変数
- プログラム終了時までメモリを確保してしまう
- 多用すると、名前がバッティングする可能性がある
- 関数内でのみ有効なローカル変数
- 関数終了時にメモリが開放される
- 宣言時に
var
をつけないと、*グローバル変数*として認識されてしまう
var hoge = 'global'; // => グローバル変数
function func () {
var fuga = 'local'; // => ローカル変数、必ずvarをつける
console.log(fuga);
}
また、他言語のようにブロックスコープは存在しない。
if (true) {
var hoge = 'block';
}
console.log(hoge); // => block ブロック内で宣言した変数も参照できてしまう
## 変数の巻き上げ(hoisting) Jsには「変数の巻き上げ」という概念がある。
var hoge = 'global';
function func() {
console.log(hoge); // => undefined なぜか global と出力されない
var hoge = 'local';
console.log(hoge); // => local 期待どおりの出力
}
一回目のconsole.log(hoge);
で、なぜかundefined
が出力されている。これが「変数の巻き上げ」の挙動。
何が起きているかというと、Jsでは、関数内のどこで変数宣言をしても、関数の先頭で、宣言のみしたと認識されてしまうため。
つまり上記のコードは以下のように処理されている。
var hoge = 'global';
function func() {
var hoge; // 初期値は入っていない。宣言のみ
console.log(hoge); // => 初期値が入っていないので、undefined
hoge = 'local';
console.log(hoge); // => 値が入っているので、local
}
これを防ぐには、変数宣言は、*関数の先頭*で行うようにする。
まとめ
- グローバル変数は多用しない
- 変数宣言時は、必ず var をつける
- ローカル変数は、関数の先頭で宣言する