Panda Noir

JavaScript の限界を究めるブログでした。最近はいろんな分野を幅広めに書いてます。

varって意味があるの?

(function($){…})(jQuery)というコードをたまにみかけませんか?このコード、初めて見るとどういう意味なのかさっぱりわかりませんよね。私もそうでした。しかし、このコード、実はとっても重要なのです。
…ということを説明しようと思ったのですが、おもいっきり二番煎じだったのでやめます。もし(function($){}(jQuery))が気になる人は(function($) {…})(jQuery);って何?って思ったからいろいろ試してみた記録をご参照ください。

今回は(function($){…})(jQuery);ではなく、varの重要性を説明したいと思います。

2013年12月23日追記:あまりにもひどい内容でわけが分からなかったので大幅に改変しました。大筋はあってたので嘘つき!と非難しないでいただけると幸いです。 2015年5月9日追記:文章がめちゃくちゃだったので修正しました。

変数についての前提知識

varの説明のためにはまず変数の種類の説明が必要です。JavaScriptの変数にはグローバル変数とローカル変数の二種類があります。

グローバル変数は、関数外で宣言された変数(関数内関数の外は関数内とします)、もしくは関数内でも関数外でもどこでもいいので宣言をしないで代入された変数です。

対し、ローカル変数は関数内で宣言された変数です。関数内で宣言しないで変数に代入しようとすると上で書いたとおりグローバル変数になってしまいます。

ローカルとグローバルの違い

さて、ここからいよいよ本題に入っていきます。JavaScriptでは変数を参照するとき、まずローカル変数を参照します。もしローカル変数で見つからなければグローバル変数を探します。ここでも見つからない場合にはエラーを返します。グローバルで宣言だけして代入してなければundefined(未定義)が返されます。

グローバル変数はコード中のどこからでも読み書き可能です。対してローカル変数は宣言した関数の外からは読み書きができません。 つまり、ローカル変数は関数の外からはアクセスされないことを保証されているセキュアな変数です。

このセキュアな変数であるという事実が名前の衝突を防ぎます。

varが防ぐ"名前の衝突"

名前の衝突とは、例えばライブラリAにhogeというグローバル変数があり、hogeには"OK"と代入されているとします。ライブラリAを使ったB.js内でhogeというグローバル変数を宣言し、hogeに"NG"と代入します(これが名前の衝突です)。するとライブラリAのhogeも変更されます。ライブラリAのhogeグローバル変数でどこからでも読み書き可能だからです。つまりライブラリAがhogeを使うときhogeは"OK"ではなく"NG"となっています。この変更がどのような影響を与えるのかは誰にも予想はつきません。

ではどうすればいいのでしょうか?答えはローカル変数としてB.js内でhogeを定義することです。変数はローカル変数が先に参照されます。そのため、B.js内でhogeを参照すると必ずローカル変数のhogeが先になります。また、ライブラリAからではB.js内のローカル変数にはアクセスできないので必然的にライブラリAのhogeが参照されます。つまり、ライブラリAのhogeと干渉しあうことはなくなります。

B.js内でhogeをローカル変数に落としこむ方法は即時関数で覆ってやることです。このへんは検索してみてください。いい記事はごろごろ転がっています。

ちなみに言っておくと他の言語では名前の衝突は名前空間という概念で防げます。JavaScriptにはない概念なので諦めましょう。

終わりに

varは変数をセキュアに、プログラムを高速にしてくれます。varはとても重要なのです。たった3文字です。みなさんもvarを粗雑にしないようにしましょう。varを書くのが面倒だという人にはCoffeeScriptがおすすめです。