エンジニアの将来って?

現在6年目の元COBOL現Javaエンジニアが、将来への考えや勉強のアウトプット、たまに腎臓について書くブログです

【JavaScript】巻き上げ、ホイストをできるだけ分かりやすく解説します

こんにちは。たいら(@tairaengineer2)です。
今回はJavaScriptのアウトプット記事です。
この記事ではJavaScriptの特有の「巻き上げ」または「ホイスト」と呼ばれる考え方について解説します。

巻き上げ、ホイストとは

ここから呼び方を巻き上げで統一させて頂きます。

JavaScript の変数にまつわる独特な点として、例外を発生させることなく後に宣言した変数を参照できる点が挙げられます。この考え方は巻き上げとして知られています。

文法とデータ型 - JavaScript | MDNから引用させて頂きました

どうやらJavaScript独特な考え方のようです。
後に宣言した変数を参照できるとはどういうことでしょうか?
実際のプログラムをご覧ください。

解説プログラム

今回解説に使うプログラムはJavaScriptが1ファイル、HTMLが1ファイルです。
HTMLからJavaScriptを呼び出して、表示させるだけの簡単なものです。

フォルダ構成

フォルダはこのようにしています。

f:id:Tairax:20180524204257p:plain

JavaScript

var country = "Japan";

function countryDisplay() {
	document.write("1回目の表示:" + country + "<br />");
	var country = "Amelica";
	document.write("2回目の表示:" + country +  "<br />");
}

HTML

<!DOCTYPE html>
<html>
	<head>
		<title>変数の巻き上げ、ホルスト</title>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<script type="text/javascript" src="../js/HoistingSample.js"></script>
	</head>
	<body>
		<script>
			countryDisplay();
		</script>
	</body>
</html>

実行結果

ではHTMLを表示させてみます。

f:id:Tairax:20180524205014p:plain

なんと!このように1回目がJapanではなく、undefinedで表示されるんです。
これが巻き上げです。

解説

何故このようなことが起きるのでしょうか?
先ほど引用したドキュメントを読み進めてみましょう。

JavaScript の変数は、ある意味「巻き上げられ」、関数や文の先頭まで持ち上げられます。 しかし、巻き上げられた変数は undefined 値を返します。そのため、変数を使用したり参照した後に宣言や初期化を行うと、 undefined が返されたままになります。

文法とデータ型 - JavaScript | MDNから引用させて頂きました

つまり、書いた私の意図としては順番通りに読み込んで

1回目の表示:Japan
2回目の表示:Amelica

というように表示して ほしいのですが、JavaScript側が

var country = "Japan";

function countryDisplay() {
	var country;
	document.write("1回目の表示:" + country + "<br />");
	country = "Amelica";
	document.write("2回目の表示:" + country +  "<br />");
}

というように変数の宣言を関数の最初に巻き上げて読んでいます。
countryには初期値が設定されていないため、1回目の表示ではundefinedが表示されるというわけです。

巻き上げを回避する方法

巻き上げに出くわすと思わぬバグが生まれる可能性があります。
なので、できるならば避けたいところです。
巻き上げを回避するには、次の方法があります。

同じ名前の変数を宣言しない

当たり前ですが、まずこれですね。
JavaScriptではグローバル変数ローカル変数を同じ名前にしてもOKです。
だからといって同じ名前にすると、巻き上げだけでなく色んなバグが生まれます。
なので、名前は違うものにした方が良いでしょう。
さらに分かりやすいものだったら最高です。

ローカル変数の宣言を関数の最初に宣言する

変数の宣言が関数の最初に巻き上げられるのなら、始めから関数の最初に宣言しちゃいましょう!ということです。
最初に宣言することで、少なくとも巻き上げが発生することはなくなります。
なので、バグが発生するのを抑えることができます。

まとめ:巻き上げには気を付けましょう

いかがでしたか?
以上がJavaScriptの独特の考え方の巻き上げについての解説記事です。
皆さんのご理解に少しでもお役にたてれば幸いです。
ではでは~(・ω・)ノシ

参考にさせて頂いたサイト様

javascriptにおける変数の巻き上げをざっくりまとめ - Qiita

 

他にも勉強記事を書いています。
良ければ、ご参考ください。

JavaのTreeSetの特徴を分かりやすく解説します。 - エンジニアの将来って?

JavaScriptで乱数を生成 - エンジニアの将来って?

eclipseのダウンロードから初起動までをできるだけ分かりやすく解説します - エンジニアの将来って?