Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. JavaScriptIntermediate - About JavaScript Scope

About JavaScript Scope - Japanese Only

みなさまどうも。

続きまして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()』について解説していきたいと思います。引き続き頑張っていきましょう。ではー。

This article was written by Sakurama.

Author's beloved small mammal

桜舞 春人 Sakurama Haruto

A Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him.

If you find any errors or copyright issues, please .