JavaScriptのホイスティングについて調べてみた
JavaScriptにはどうやら、"ホイスティング (hoisting)"なる仕様があるらしいので、今回はそれを勉強した結果をまとめてみようと思います。
ホイスティングとは?
ホイスティングは"hosting"と書くようです。英語で"hoist"は揚げる、持ち上げる、つり上げる、巻き上げるなどの意味があるようです。日常会話じゃ使わない英語だなぁ。。。
JavaScript的に言えば、"JavaScriptは関数内のどこでもvarで変数宣言をすることができるが、それらの変数は、どこで宣言したとしても、常に関数の一番戦闘で宣言されたように動作する"ということのようです。
つまり、
(function(){ console.log("a: " + a); var a = 1; })();
というコードであれば、
(function(){ var a; console.log("a: " + a); // Undefined a = 1; })();
ということになり、console.logで使っている時点ではaの変数はundefinedになるということになりますね。
上記くらいシンプルな例だったら分かりやすいですが、これが複雑になってくると、いろいろと不具合も起きそうです。ちょっとググっただけでも、
・「変数は常に関数の先頭で宣言するようにしましょう」
・「ホイスティングは絶対にさせるべきではない」
・「ホイステイングが原因になる不具合を避けるために、coffee-scriptを使いましょう」
という内容がみつかりました。
何か非常に問題児扱いされているホイスティング、何故JavaScriptがこんな仕様になっているか、調べてみました。
何故ホイスティングって仕様が存在するのか?
・http://stackoverflow.com/questions/15005098/why-does-javascript-hoist-variables ーホイスティングはJavaScriptのインタプリタの仕様のため。 ーJavaScriptのコードの解釈(interpretation)は2つの方法がある ーStep 1: varあり変数(declared variable)と関数文(Function declaration)を解釈する ーStep 2: 解釈した関数式(Function expression)とvarなし変数(undeclared variable)を解釈(process)し、コードを実行する。 ー上記2つのステップのためにホイスティングは存在する
つまり、スコープが先に決まるものを先に実行解釈し、その後にスコープが実行時の状況に応じて変わるものを解釈、実行するわけですね。まあ、考えてみればそりゃそうですね。
なので、ホイスティングは、
(function(){ console.log("a: " + a); var a = 1; })();
のconsole.log("a: " + a);のaって何モノ?(=どのScopeのaなの?)を知るために、
(function(){ var a; console.log("a: " + a); a = 1; })();
というように解釈することで、どのaを参照するか?を決めるために使われる言語仕様、ということができるでしょうか。
※この場合は出てきていないですが、同じaという名前の変数が、グローバルにもある可能性がありますからね。
現状、いろいろと記事を読みながら僕が理解したホイスティングです。
もち間違っていればご指摘くださいませ〜。