JavaScriptのグローバル変数を解説!ローカル変数と違いとは
JavaScriptでプログラミングをしていると変数を定義する場面が多く出てきます。何も難しいことはありませんが、ローカル変数との兼ね合いでバグが起こることもあるため正しい知識を持って使わなければなりません。そこで、グローバル変数とは何者なのか、そしてスコープの概念についても知っておく必要があるでしょう。グローバル変数でつまずくことのないよう、ここで基本事項をきちんと理解しておくようにしましょう。
JavaScriptにおけるグローバル変数とは
「グローバル変数」はプログラムのどこからでもアクセスができる変数のことです。これに対して関数の内側で宣言した変数は「ローカル変数」と呼ばれ、どこででも使用できる変数ではありません。
他の多くのプログラミング言語でも同じですが、JavaScriptにおいてもどこでどの変数が使えるのかということは意識していなければなりません。ローカル変数を定義する場面も多くありますが、それぞれが有効に機能する場所というものがありますので、そのことを前提にプログラムは組まなければなりません。
そしてグローバル変数とローカル変数との関係や、名前が被ってしまったときの挙動、優先度などについてはよく理解しておく必要があるでしょう。
スコープとは
グローバル変数やローカル変数の違い、それぞれの特徴を理解する上では「スコープ」と呼ばれる概念を知っておくことが必要です。
スコープとは、変数がプログラムの中のどの場所から参照できるのか、ということを決定づけるものです。変数が使用可能な範囲と言い換えることもできます。そしてグローバル変数ではプログラムのどこからでも参照ができるため全範囲がグローバル変数にとってのスコープとなり、これを「グローバルスコープ」と呼びます。一方でローカル変数では有効な範囲が限られ、これを「ローカルスコープ」と呼びます。
グローバル変数の定義方法
グローバル変数として定義するには関数の外で変数の宣言をします。
var ghensu = 'Global';
console.log(ghensu);
//Global
任意の変数名の前にはvarを記述し、ここに値を代入していきます。ここでは「Global」という文字を代入します。
そして確認のためにこれを出力してみると、その文字が表示されることが確認できます。
ローカル変数の定義方法
ローカル変数は関数内で宣言した変数のことですので、まずは関数を定義し、その中で変数を定義することになります。
function local(){
var lhensu = 'Local';
return lhensu;
}
console.log(local());
//Loccal
このプログラムでは関数local()の中で「lhensu」という変数を定義し、「Loocal」という文字を代入しreturnでその値を返しています。そして定義した関数を呼び出すことでローカル変数の値が出力されています。
varの使い方に注意
ここまで当たり前のように変数宣言で「var」を使ってきましたが、これは必ずしも必要なものではありません。実際、グローバル変数とローカル変数の定義で紹介したプログラム例のどちらも「var」なしで同じ出力結果が得られます。ただしこの場合、不具合が出てくることもあるので注意しましょう。
というのもJavaScriptで「var」を使わずに宣言した変数はすべてグローバル変数とみなされる、という特徴があるためグローバル変数とローカル変数で同じ変数名を使用していると予期せぬ場所で変数が上書きされてしまうことがあるのです。そのためローカル変数はもちろん、グローバル変数の定義でもすべて「var」を使うことが推奨されます。
ES6ではletで変数定義
ES6では「let」も追加されており、ES6が利用できる環境では「var」の代わりに「let」を使って変数を定義すると良いとされています。また、ある決まった値を使うのであれば定数として定義する方法もあります。
const 定数名 = 値
このように、変数のときと似た形で定義することができます。
「let」に関してもほとんど「var」と同じように使用できますが、スコープの範囲には注意が必要です。「var」だと関数スコープとなり、関数内でブロックで変数定義をしても同名だと上書きされてしまいます。
一方「let」ではブロックスコープですので同じ関数内で同名の変数を定義してもブロックさえ異なっていれば違うものとして呼び出すことができます。「var」ではブロックスコープまでは対応していませんが、「let」ではブロックスコープに対応するため、下の例のように「let」で定義したものをブロック外で出力しようとするとエラーが起こります。
if (true) {
var value1 = 10;
console.log(value1);
}
console.log(value1);
if (true) {
let value2 = 20;
console.log(value2);
}
console.log(value2); // → エラー
グローバル変数の優先順位
「var」で宣言することなく変数定義をした場合にはすべてグローバル変数とみなされてしまいますが、varを使った場合でもどちらの変数がどの場所で優先されるのかは理解しなければ結局混乱してしまいます。そこで変数の優先関係についていくつか説明していきます。
関数内ではローカル変数が優先される
グローバル変数とローカル変数で同じ変数名が使用されている場合のプログラムを見てみましょう。
var hensu = 'Global';
console.log(hensu);
function local(){
var hensu = 'Local';
console.log(hensu);
}
local();
console.log(hensu);
//Global
//Local
//Global
最初にグローバル変数「hensu」が定義されています。直後に変数の値を出力し、当然代入した「Global」が表示されます。その下では関数local()が定義され、ローカル変数として同じく「hensu」が定義、そして関数を呼び出してその変数の値を出力させています。すると、同じ console.log(hensu)
という処理をさせているにも関わらず結果は「Local」が表示されています。しかし関数の外で再び同じことをさせるとグローバル変数が出力されています。
つまり、関数内で定義されたローカル変数はその関数内部でしか有効に機能しませんが、損範囲内ではグローバル変数に優先するということが分かります。そしてこれは上書きをしているわけではなく、それぞれの変数は別物として扱われ関数の外に出れば再びグローバル変数を使うことができます。
変数の巻き上げに注意
グローバル変数を使うには最低限、前項で説明したローカル変数との優先度が理解できればほとんど問題はありません。しかし、下のプログラムを見れば分かるように、ほぼ同じ処理をさせているにも関わらず結果が変わってしまうこともあるので変数の定義は、初めのうちは慎重に行う必要があるでしょう。
var hensu = 'Global';
console.log(hensu);
function local(){
console.log(hensu);
var hensu = 'Local';
}
local();
console.log(hensu);
//Global
//undefined
//Global
前のプログラムと違う点は関数内で変数定義をする前に出力させているということです。
この場合、グローバル変数が適用されても良いようにも思えますが結果は「undefined」となり未定義の変数とみなされてしまいます。ローカルスコープの範囲ではありますが、まだ変数定義がされていない状態で出力しようとするとこのような挙動を起こしてしまいます。これを「変数の巻き上げ」と呼びます。そのため、JavaScriptでは関数の先頭でローカル変数を定義するのが望ましいとされています。
まとめ
JavaScriptにおけるグローバル変数の意味やその定義方法、そしてローカル変数との関係について説明してきました。覚えておきたいのはグローバル変数を定義していたとしてもローカル変数を定義したその関数内ではローカル変数が優先されるということ、そしてどの変数であったとしても定義時には「var」を使うということです。また、定数であれば「counst」、そしてES6の環境では「let」を使って定義をしていきます。特に「let」では「var」とのスコープの違いに注意が必要ということでした。
グローバル変数を使いこなして混乱のないようにしていきましょう。