みみぺんブログ

WEBデザイナー、エンジニア、プログラマー向けの記事を投稿します

スコープ(scope)について【JavaScript初心者入門】

JavaScriptの第一歩 スコープ(scope)について
JavaScriptの「スコープ」について


はじめまして、かずん(@kazoonLab)と申します。


私の担当する記事では、主にJavaScript(JS)まわりの技術や、各種ツールの紹介をしていく予定です。プロフィールはこちらに載っているので、そちらをご覧ください。


本日は、JavaScriptの基本、「スコープ」について紹介していきます!


スコープとは


JavaScriptのスコープ(scope)とは、「ある変数や関数の引数を参照・更新できる範囲を示したもの」です。


スコープ内で定義された変数はスコープの中でのみ参照することができます。逆に言えば、スコープの外では参照することはできません。


JSには様々なスコープがあります。まずは、一番大きな「グローバルスコープ」の例を見てみましょう。

グローバルスコープ(global scope)

// グローバルな変数を定義
var global = 'global';

// グローバルな関数を定義
function globalFunc () {
	console.log('This var is ' + global);
};

// 関数を呼び出す
globalFunc();  // --> This var is global

// 変数を更新し、関数を呼び出す
global = 'grobal2';
globalFunc();  // --> This var is global2


グローバルな変数は、プログラムのあらゆる場所から値を参照・更新できます。


一見よさげに見えますが、意図せず値を書き換えてしまったりする恐れがあります。


変数がどこまで有効であるかをハッキリさせるため、JSには「関数スコープ」というものがあります。


サンプルソースを見てみましょう。

関数スコープ(functional scope)

// グローバルな関数を定義
function globalFunc () {
	// 関数内でローカルな変数を定義
	var local = 'local';
	// 関数内でローカルな関数を定義
	function localFunc () {
		console.log('This var is ' + local);
	}
	// ローカルな関数を呼び出す
	localFunc();
};

// グローバルな関数を呼び出すと、ローカル関数が呼び出される
globalFunc();  // --> This var is local

// グローバル関数を経ず直接ローカル変数・ローカル関数を参照・実行することはできない
console.log(local);  // --> undefined
localFunc();  // --> undefined

// ローカル変数と同じ名前で変数を定義しても、ローカル変数には影響はない
var local = 'not local';
console.log('This var is ' + local);  // --> This var is not local
globalFunc();  // --> This var is local


関数スコープを用いると、影響範囲を関数の中だけに限定した変数・関数を定義できます。


関数の外で値が更新されることはないため、プログラムの保守性がぐんとあがります。


大事なこととして、変数を宣言する際、必ず「var」をつけてください。こちらは、後ほど出てくるlet, constと合わせ、次回の記事で紹介したいと思います。


最後に、関数スコープと似て非なる「ブロックスコープ」を紹介します。

ブロックスコープ(block scope)

ブロックスコープとは、{}を書く文で作られるスコープを指します。
具体的には、if, else, for, while, switch, try, catch, ... などです。
例を見てみましょう。

// グローバルな関数を定義
function block() {
        // var を用いてローカル変数を宣言
	var localVar = 'localVar';
        // let を用いてローカル変数を宣言
	let localLet = 'localLet';

	if(true) {
                // ブロック(if文)の中でローカル変数を上書き
		var localVar = 'localVar2';
		let localLet = 'localLet2';

		console.log('if文の中ののlocalVarは' + localVar);  // --> if文の中ののlocalVarはlocalVar2
		console.log('if文の中ののlocalLetは' + localLet);  // --> if文の中ののlocalLetはlocalLet2
	}

        // ブロックを通った後、localVarは更新されているのに対し、
        // localLetは最初に宣言したままの値が入っている
	console.log('if文を抜けた後のlocalVarは' + localVar);  // --> if文を抜けた後のlocalVarはlocalVar2
	console.log('if文を抜けた後のlocalLetは' + localLet);  // --> if文を抜けた後のlocalLetはlocalLet

}

block();


ブロックスコープを用いることで、ブロックの中でのみ参照できる変数を作ることができます。


関数スコープよりさらに小さい感じがしますね。


なお、ブロックスコープを作る際は、変数をlet、もしくはconstで宣言する必要があります。


let、constの説明は、次回の記事でより詳細にしたいと思います。


まとめ

様々なスコープを見てきましたが、より影響範囲の小さい(バグの出にくい)変数を作るため、なるべくブロックスコープを使えると良いかと思います。


当然、関数全体で使用するなら関数スコープを使わなければなりませんし、windowオブジェクトのようにそもそもグローバルな変数なものもあります。


「この変数はここでしか使わない」という小さな判断の積み重ねが、可読性の高い、整然としたソースコードにつながっていくことでしょう。


次回の記事では、接頭辞(var / let / const)の性質についてとことん語ります!


最後までご覧いただきありがとうございます。


この記事がいいなっと思ったら読者登録をお願いいたします♪


【ツイッター】
技術者の方ともっと繋がりたいっす!お気軽にフォローもお願いします!
かなきち
かずん