More than 1 year has passed since last update.

JavaScriptのスコープについて

はじめに

この記事を読めばJavaScriptのスコープについては中級者程度の知識は得られると思います。拙い説明ですが、何かの参考になれば幸いです

スコープって何?

スコープとは変数名や関数名の有効範囲のことです。

スコープって何のために意識するの?

スコープを意識することで同名の変数を別のものとして使い回すことが可能となります。これは大規模開発などにおいては必要不可欠なのではないでしょうか。逆に考えれば、スコープを意識しておかないと、意図せぬバグを引き起こしてします可能性が高いでしょう。

スコープの種類

スコープには二つの週類があります。一つはグローバルスコープ。もう一つは関数スコープです。それぞれ順に説明していきたいと思います

グローバルスコープとは

グローバルスコープとは関数の外のスコープです。より具体的には関数の外で宣言された変数や関数はグローバルスコープに含まれます。

ローカルスコープとは

ローカルスコープは反対に関数の中のスコープです(ゆえに関数スコープともいますが、筆者はローカルスコープの方がわかりやすくていい気がします)。より具体的には関数の中で宣言された変数や関数はその関数スコープに含まれます。

グローバルスコープとローカルスコープの違いって何?

基本的にグローバルスコープで定義された関数や、変数はどこからでもアクセス可能です。ただしローカルスコープ内に同じ変数名があった場合、ローカルスコープ内での変数呼び出しはローカル変数が優先されるなどの例外があります。それとは逆にローカル変数はそのローカルスコープの中でしかアクセスできません。

var hoge = "global";

function showHoge(){
  print(hoge); //undefined
  var hoge = "local";
  print(hoge); //local
  return hoge;
}

print(showHoge()); //local
print(hoge); //global


上のコードからグローバルスコープ宣言されたhogeはshowHoge内の影響は受けておらず、逆にshowHoge関数内で宣言されたhogeはグローバル変数の影響を受けていないことがわかります。またさらに気をつけるべき1つ点があります。それはローカルスコープ内で宣言されたhogeをそのローカルスコープ内で最初に出力しようとした時にundefinedとなってしまっていることです。これはどういうことかというと、showHoge関数のスコープの中ではhogeが示すものはすでにグローバル変数ではなく、ローカル変数になっています。これはローカルスコープ内での宣言前でも同様です。しかし、宣言前の場合はundefinedになってしまうので、注意が必要です。

ブロックスコープがJavaScriptにはない

他の言語を学んだことがある方は最初に述べたスコープの種類にブロックスコープがないことに疑問を感じるかもしれません。なんとJavaScriptにはブロックスコープはありません。これによって生じる主な勘違いは次のようなことでしょう

var i = 1;
for(var i = 0; i<4 ; i ++){
  処理
}
print(i); //4

おそらく最後の出力結果が1ではないかと思った方もいらっしゃると思いますが、JavaScriptにはブロックスコープが存在しないので、ここでの出力結果は4となります。

ブロックスコープを作る方法

実はECMAScript第5版にはブロックスコープを作り出せるletが存在します。letの使い方にはlet宣言とlet文の2通りがあります(ややマニアックなような気もする)。

let宣言.js
var hoge2 = "グローバル";

if (true){
  let hoge2 = "ブロック";
  print(hoge2); //”ブロック”
}

print(hoge2); //”グローバル”
let文.js
var hoge3 = "グローバル";

let (hoge3 = "ブロック"){
  print(hoge3); //”ブロック”
  hoge3 = "block";
  print(hoge3); //"block"
}

print(hoge3); //”グローバル”

letに関してはいずれもそんな使い方があるんだなー程度にとどめてもらって構わないと思います。

入れ子のスコープ

関数が入れ子になっている場合、基本的にスコープは「中から外」の考え方でうまくいきます。言葉で説明するより実際に見てみた方が早いので例を見てみましょう。

var lastname = "かずき";

function changeName{
  var lastname = "ともき";
  print(lastname); //"ともき" 

 function addFirstName(){
    var lastname = "さとうかずき";
    print(lastname); //"さとうかずき"
  }

}

ここまで読み進めてくださった読者の方には割と納得いく結果ではないでしょうか?これは言葉で説明するより感覚的にわかりやすいかなと思います。(ちなみにさとうかずきはもちろん架空の存在です)

終わりに

いかがだったでしょうか?実際にはまだまだJavaScriptのスコープには色々とありまして。特にクロージャに関しては上級者と中級者を分ける鍵なのかな、と思いますが(僕は口が裂けても自分のことを上級者とは言えませんし)、なかなか難しい上に長くなってしまうので、また別の記事にさせていただこうかなと思います(完成次第ここにリンクも載せます)。最後になりますが、少しでもJavaScriptの学習の手助けになれれば、ありがたいです。間違い等ありましたら、ご遠慮なく申し出てください。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.