Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

  1. トップページ
  2. JavaScript中級編 - JavaScriptのスコープ

JavaScriptのスコープ

みなさまどうも。

続きましてJavaScriptでの『スコープ』について解説していきたいと思います。

当サイトではこれまで『変数』、『配列』、『オブジェクト』などを紹介してきました。実はそれらにアクセスできる有効範囲というものが決められていたりします。これをプログラミングの世界では『スコープ』と呼びます。『スコープ』はほぼ全てのプログラム言語に存在している概念です。

以下のサンプルを見てください。

function hoge(){
    var x = 0;
}
hoge();

console.log(x);

上記のサンプルでは関数『hoge』を定義し、その中で変数『x』に『0』を代入しています。

それを関数の外から『console.log(x)』で変数『x』の値を出力しようとしているのですが、実行してみると以下のようになります。

「変数『x』は定義されてないよー」とエラーになっていますね。

じゃあ関数の中で『console.log(x)』を実行させてみましょう。以下のような感じですね。

function hoge(){
    var x = 0;
    console.log(x);
}
hoge();

そうすると以下のようになります。

ちゃんと『0』と出力されていますね。

このようにJavaScriptでは関数の中で定義された変数やオブジェクトは関数の外からアクセスすることができません。関数の中で定義された変数やオブジェクトを操作したい場合は同じ関数の中で処理を記述する必要があります。

なので違う関数で同じ変数名やオブジェクト名を定義してもそれは全く違うものとして扱われます。

function hoge(){
    var x = 0; // これは関数『hoge』の中の変数『x』
    console.log(x);
}
function hoge1(){
    var x = 1; // これは関数『hoge1』の中の変数『x』
    console.log(x);
}
hoge(); // 『0』と出力される。
hoge1(); // 『1』と出力される。

これが『スコープ』の概要になります。

ではもうちょっと色々試してみましょう。先程は関数の中で変数を定義していましたが関数の外で変数を定義したらどうなるでしょうか。以下のような感じですね。

var x = 0;

function hoge(){
    console.log(x);
}

function hoge1(){
    console.log(x);
}

hoge();
hoge1();

これを実行してみると以下のようになります。

全ての関数の中から変数『x』にアクセスできているようですね。関数の外で定義された変数やオブジェクトはどこからでもアクセスすることができます。

このような感じでどこからでもアクセスできる変数は『グローバル変数』と呼ばれます。対して同じ関数の中からしかアクセスできない変数は『ローカル変数』と呼びます。オブジェクトの場合は『グローバルオブジェクト』、『ローカルオブジェクト』となりますね。

と、『スコープ』の概要はこんな感じになりますがプログラミングに慣れていないと良く分からない感じがすると思います。

なぜこんな使いづらそうな仕様になっているのかというと、変数名、オブジェクト名のバッティング(同じ名前で定義してしまうこと)を避けるためです。

『スコープ』という機能が存在しなかったとしましょう。そうすると全ての変数名、オブジェクト名を確認して使われていない言葉のリストを作らなくてはいけません。もしすでに使用されている言葉で変数を定義してしまったりしたら前に書かれている処理を上書きしてしまい、その処理が動かなくなってしまいますので大変です。

『スコープ』という機能があれば自分で定義した関数の中では好きな名前を使って処理を構築することができますね。前に書かれている処理を上書きしてしまうといった事故は起こりません。なのでほぼ全てのプログラム言語で『スコープ』という概念が組み込まれています。

JavaScriptでは『var』を記述しないで変数宣言、オブジェクト宣言などを行うと『グローバル変数』(グローバルオブジェクト)として定義されます。

function hoge(){
    x = 0; // これはグローバル変数『x』として定義されます。
}

関数の中から『グローバル変数』(グローバルオブジェクト)を定義できるので状況によっては非常に有用なテクニックです。逆に『var』を書き忘れると全てが『グローバル変数』(グローバルオブジェクト)として定義されてしまうので書き忘れには十分ご注意ください。

『スコープ』は色々な言語で実装されている概念となりますが、言語によってスコープの範囲が大きく違います。なので他のプログラム言語を記述する際は『スコープ』の有効範囲を必ず確認するようにしてください。

さて、『スコープ』という概念を解説したところでちょっと注意点があります。他のプログラム言語でも言えることですが、『グローバル変数』(グローバルオブジェクト)の定義は極限まで避けるようにしてください

『グローバル変数』(グローバルオブジェクト)はどこからでもアクセスできるため非常に便利な気がするかもしれません。しかし逆に考えるとどこからでもアクセスできるということはどこからでも上書きができるということになります。

仮に、とある変数の上書きが原因でバグが発生したとしましょう。その原因となった変数がローカル変数ならばその変数が定義されている関数の中のみチェックすれば修正することができますが、グローバル変数だったら全てのソースコードを確認しないといけません。

その他、グローバル変数を定義すればするほど使用できる名前が減っていきます。Aさんが『elem』というグローバル変数を定義して、Bさんが『x』というグローバル変数を定義して〜、と繰り返していくともう大変です。

プログラムが大きくなればなるほどその影響は大きくなってきます。なのでその関数でしか使わない変数は必ずローカル変数として定義し、他の関数にまたがって使用する変数のみをグローバル変数として定義するようにしましょう。

最初のうちはちょっと難しいかもしれませんが頑張ってください。

JavaScriptでの『スコープ』は関数スコープしか存在しません。

なので関数の中なのか、それとも外なのかだけ確認すればそのソースコードの中の『スコープ』は把握できるかと思います。

と、『スコープ』についてはこんなところですね。

昨今のJavaScriptではグローバル領域を汚染しないように『即時関数』でラップする、という技法が使われていますがそれは先の記事で紹介します。

続いての記事では『setTimeout()』と『setInterval()』について解説していきたいと思います。引き続き頑張っていきましょう。ではー。

この記事は桜舞が執筆致しました。

著者が愛する小型哺乳類

桜舞 春人 Sakurama Haruto

ISDN時代から様々なコンテンツを制作しているちょっと髪の毛が心配な東京在住のプログラマー。生粋のロングスリーパーで、10時間以上睡眠を取らないと基本的に体調が悪い。好きなだけ寝れる生活を送るのが夢。ゲームとスポーツと音楽が大好き。誰か髪の毛を分けて下さい。

記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。