1. HOME
  2. ブログ
  3. エンジニアになろう!
  4. 【JavaScript】スコープを意識して保守性の高いコードを作ろう

【JavaScript】スコープを意識して保守性の高いコードを作ろう

JavaScriptのスコープについて

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

関数や変数は定義されたスコープ内でしか影響を与えることが出来ません。

ざっくりとスコープの概要を解説します。

まずはこちらのサンプルコードをご覧ください

【実行結果】
ReferenceError: hello is not defined

上記のサンプルでは、関数 func() の中で 変数 hello を定義し、関数 func() から変数 hello を呼び出そうとしています。

実行すると ReferenceError: hello is not defined とエラーが表示されてしまいました。

「変数 hello は定義されていない」と怒られてしまいます。

次にこちらのサンプルコードをご覧ください

【実行結果】
hello world

上記のサンプルでは、関数 func() の中で 変数 hello を定義し、関数 func() から変数 hello を呼び出そうとしています。

今回は、エラーがでることもなくメッセージを表示できました。

つまり、関数内で定義された変数は、関数内でしか実行できません。

関数内で定義された変数は、関数内でしか実行できない

関数内の変数の記憶領域は、関数が終了時に破棄されます。

そのため、一番最初で示したサンプルコードではエラーが表示されました。

異なる関数で同名のの変数やオブジェクトを定義しても、それは別物として扱われます。

ミツオカミツオカ
ちなみに、スコープを意識する必要性は?

にゃんこ師匠 にゃんこ師匠
スコープを意識する…つまりは変数や関数の有効範囲を意識すること、影響範囲を意識することだにゃ

ミツオカミツオカ
変数の影響範囲を必要最低限に抑えることで、保守性の高いプログラムになるということですね

にゃんこ師匠 にゃんこ師匠
うむ!ちなみにスコープの種類としては3つあるので覚えておくのだ
1. グローバルスコープ
2. 関数スコープ
3. ブロックスコープ ( ES2015/ES6 以降)

グローバルスコープ

グローバルスコープとは、関数の外(トップレベル)で定義した変数、関数になります。

また var をつけずに変数を定義した場合も、グローバルスコープの変数になります。

グローバル関数

グローバルスコープの変数、関数をグローバル変数、グローバル関数と言います。

グローバルスコープの変数は、プログラムのどこからでも呼び出すことができ、値を変更することもできます。

どこからでもアクセスできるため、プログラムが大きくなればなるほどに影響範囲が大きくなります。

サンプルコード

グローバル変数globalScope関数globalFunc()で呼び出しています。

その後、変数の値を変更しています。

【実行結果】
this is global
this is global2

変数の中身は変更されていることが確認できます。

注意事項

グローバル変数は極力使わないようにプログラムを作成してください。

なぜならグローバル変数の値を変更した場合、プログラム全体に影響を及ぼします。

影響範囲が広いということは、なにかバグが発生したり、ソースコードを改修するときに、調べなければならない範囲が広いことになり、プログラムの保守性が低下します。

関数スコープ(ローカルスコープ)

関数スコープとは、関数の中で定義した変数、関数です。

関数内の中だけその変数を利用することができます。

変数の影響範囲が関数内に限られるため、プログラム全体への影響を抑えることができます。

サンプルコード

関数 globalFunc() の中でローカル変数 localScope を呼び出しています。

また、関数globalFunc() の外から、ローカル変数 localScope を呼び出しています。

【実行結果】
This is local
ReferenceError: localScope is not defined

実行結果をみると、スコープ外からローカル変数localVal を呼び出していたためエラーがでており、ローカル変数の影響範囲が限定的であることが確認できます。

ブロックスコープ

JavaScript の最新仕様 ES2015 (ES6) からブロックスコープの変数 let 、 const が利用可能となりました。

ブロックスコープは変数の影響範囲が、関数スコープよりも小さく、{} で囲まれた範囲になります。

そのため変数の影響範囲を for 文 や if 文の範囲で収めることができます。

:let を使った例

{}でそれぞれ変数outBlock , inBlock を定義し、ブロックスコープの影響範囲を確認します。

【実行結果】
inside
calloutBlockVal
callinBlockVal
outside
calloutBlockVal
ReferenceError: inBlock is not defined

実行結果を見てみると、{} の内側で定義した変数は、 {} の外側で呼び出したときにエラーがでることが確認できます。

var を使った例

var で定義した変数はブロックスコープにはなりません。

そのため{}の内側で var を用いて変数を定義すると、{}の外側からでも変数にアクセスできます。

【実行結果】
inside
calloutBlockVal
callinBlockVal
outside
calloutBlockVal
callinBlockVal

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

JavaScript の解説記事には「ブロックスコープがない」という記述が散見されます。

しかし、先述のように JavaScript にもブロックスコープは存在します。

ただし、ブロックスコープの仕様が定められたのが、2015年のため古いブラウザでは対応していない場合があります。

let・const のブラウザの対応状況

現在のブラウザの対応状況は以下で確認できます。

ECMAScript 6 compatibility table

現在の最新ブラウザ ( Edge, Chrome, Firefox, Safari ) は標準で対応しています。(IE 11 では一部未対応)

古いブラウザまでサポートに含める場合、Babel 等のトランスパイラを利用して、ES5 のコードに変換する方法がとられます。

にゃんこ師匠 にゃんこ師匠
みっちゃん、今回の記事をまとめるのだ

ミツオカミツオカ
1. JavaScript には変数の影響範囲をきめるスコープがある
2. グローバルスコープの変数、関数の影響範囲は、プログラム全体に及び、どこからでもアクセスできる
3. ローカルスコープ(関数内で定義した)変数、関数の影響範囲は、関数内に留まる
4. ブロックスコープ(let, const で定義した変数、関数)の影響範囲は、{} に囲まれた範囲に留まる
にゃんこ師匠 にゃんこ師匠
スコープを意識することで、変数の有効範囲を限定でき、バグが少なく保守性の高いコードを作成することができるのだ

ミツオカミツオカ
スコープを意識したプログラム作りの大事さが分かりました~!

一緒に働いてくれる仲間を募集中!

ライトコードでは、仲間を募集しております!

ライトコードのモットーは「好きなことを仕事にするエンジニア集団」。そのため、あなたがやりたい仕事を全力で応援します。

どうせなら、好きなことを仕事にする方が人生は何倍も素晴らしいものになるはず!また、ライトコードはこれからの会社ですので、みんなで新しい事業や組織を作っていく楽しみもあります。

あなたからのご応募をお待ちしております!

ライトコードでは一緒に働いていただける方を募集しております!
お気軽にご応募ください。

採用情報はこちら

書いた人はこんな人

ライトコードメディア編集部
ライトコードメディア編集部
「好きなことを仕事にするエンジニア集団」の(株)ライトコードのメディア編集部が書いている記事です。

関連記事