こちらの技術書のスコープについてのまとめです。
グローバル変数とローカル変数の違い
- 関数の外で宣言した変数 → グローバル変数
- 関数の中で宣言した変数 → ローカル変数
var scope = 'Global Variable'; //グローバル変数
function getValue() {
var scope = 'Local Variable'; //ローカル変数
return scope;
}
console.log(getValue()); //結果: Local Variable
console.log(scope); //結果: Global Variable
getValue
という関数を入力するとその関数内で定義したscope
という変数が、scope
という変数そのものを入力するとグローバルで定義した変数scope
が返される。
つまり、スコープが異なる場合、それぞれの変数は同名であっても別物として認識されている。
変数宣言にvar命令が必須な理由
scope = 'Global Variable'
function getValue() {
scope = 'Local Variable';
return scope;
}
console.log(getValue()); //結果: Local Variable
console.log(scope); //結果: Local Variable
また、JavaScriptではvar命令を使わずに宣言された変数はすべてグローバル変数と見なす。
そのため、ローカル変数として定義したつもりであるLocal Variable
がグローバル変数とみなされてしまう。
上の例では最初にグローバル変数として定義したscope
が関数内で定義したscope
に上書きされる。
そのため、先ほどの例ではGlobal Variable
を返したconsole.log(scope);
は関数内で定義されているはずのLocal Variable
を返す。
なのでローカル変数を定義する時には、必ずvar命令(もしくはlet, const)を使用する。
ローカル変数の有効範囲
var scope = 'Global Variable';
function getValue() {
console.log(scope); //結果: undefined
var scope = 'Local Variable';
return scope;
}
さっきとほぼ同じだが、ローカル変数定義前に関数内で変数scope
を受け取ろうとすると、undefined
となる。
理由としてJavaScriptのローカル変数は関数全体で有効であるため、console.log(scope);
時にはローカル変数を返そうとしてくれる。
しかし、ローカル変数が定義されているのは出力を試みた後なので、何も返されず、未定義として扱われる。
なのでローカル変数は関数の先頭で宣言する。
ブロックスコープ
JavaScriptでは下記のようなものでも値を返せてしまう。
if(true) {
var i = 5;
}
console.log(i); //結果: 5
しかし、プログラミングの一般的なルールで「スコープは出来る限り限定すべき」というものがある。
そこでES2015から導入されたlet
ではブロックスコープに対応できるようになった。
if(true) {
let i = 5;
}
console.log(i); //結果: エラー
同じくconst
もブロックスコープを持つ。
まとめ
- スコープは出来る限り限定すべき。
- グローバル変数は出来るだけ使わない。(デバッグが困難になる)
- ローカル変数は関数の先頭で宣言する。
- if文やswitch文ではできるだけ
let
を利用する。