[雑記]ローカルだけではできない...>2012-01-15私が今までクロージャを理解できなかった理由JavascriptJavascriptを勉強する上で誰もがつまずくと言われるクロージャですが私も例に漏れず理解できないでいました。さまざまな解説サイトを読んだりサンプルコードを書き換えてみたりして静的なスコープの言語で利用できる。関数が終了したあともそのローカル変数が参照できる。いったクロージャの「仕組み」や「特徴」については分かったものの、もっとも重要ともいえる「どういう時にクロージャを使えばいいのか」が分かりませんでした。言いかえると友人がなんて言って悩んでいる時に「そう言う時はクロージャを使うといいよ」と言ってあげればいいのか。プログラムの勉強を始めた友人が「これと同じ処理もう何回も書いてるんだよ。コピペばっかりしてる気がする」と言って悩んでいたら「そこを関数にすればいいんじゃない?」って教えてあげますよね。これと同じように友人が「○○○○○○なんだよ、うまい方法ない?」と質問して来た時に「そういう時はクロージャを使えばいいよ」と答えてあげるべき○○○○○○は何なのか。これが分かって初めて自分でもクロージャが使えるはずです。最近になってようやく私もこのクロージャをどういう時に使うべきかが分かってきました。(と自分では思ってる)それに伴い「なぜ今まで分からなかったか」という理由も分かってきたので整理したいと思います。結論から言えば「(クロージャを使うことで)関数終了後もそのローカル変数を参照できることから得られる2つの大きなメリットの内、一方を分かっていなかったから」ではないかと考えています。解説書などでよく示されているクロージャのサンプルが「自身が呼ばれた回数をカウントする関数」です。Japanでもほぼ同じサンプルが示されています。1が表示される...http://builder.japan.zdnet.com/script/sp_javascript-kickstart-2007/20378258/2/同じ機能をクロージャを使わずに書くと下のようになるでしょうか。//1が表示される両者の違いは何かと言うと「使用しなければならないグローバル変数の数」です。1が表示されると、書くこともできるためどうしても使用が避けられないグローバル変数の数は実質1つです。これに対してコード2の例ではcountという変数とcounterという変数はどちらも必ず使わざるを得ません。counterはもちろんのことcountの方も肝心の呼ばれた回数を保存しているからです。そもそもなぜグローバル変数が少ない方がいいかという話は本題からそれるので避けますがクロージャのメリットの1つがこのことである事はまちがいありません。ここまではクロージャを説明するサンプルコードでもまず間違いなくしめされています。ここからが本題ということになります。(ようやく(^_^;))関数終了後もローカル変数を参照できることのメリット2、クロージャを使うと1のメリットを享受しつつ計算量を増やさないことができるさて、上の「自身が呼ばれた回数をカウントする関数」ではクロージャを使うことでグローバル変数を減らすことができましたが、一方で計算量そのものは変化がありませんでした。グローバル変数かローカル変数かの差はあれどcounter()が実行されるたびにある変数を+1していくという処理に違いはないからです。クロージャの「関数終了後もローカル変数を参照できるという特徴」を使うと次のように普通に書くと計算量が増えてしまう場合にもそれを防ぐことができます。いう変数の値が"English"であれば"Hello"を"Japanese"であれば"こんにちは"という文字列をアラートするhello()という関数を考えてみます。何も考えずに実装すれば次のようになります。hello(){window.alert(text);}hello();lang,text,helloと3つもグローバル変数を使ってしまっています。langとhelloは無理ですがtextはいかにもローカル変数で代用できそうです。クロージャの出番か!?となるわけですがtextをローカル変数にするだけであればクロージャを使わなくても次のように書けば良いだけです。&quot;こんにちは&quot;;}window.alert(text);}hello();見事にグローバル変数はlangとhelloのみになりました。hello関数の内側に注目してください。このhello関数はtextをローカル変数にしたために関数が呼ばれるたびにlangの値が"English"なのか"Japanese"なのかを判別しなくてはならなくなってしまいました。textがグローバル変数だったコード4ではlangの中身を確認するifの処理は一度行うだけで良かったのにグローバル変数を減らした代償としてhello関数が呼ばれるたびに毎回毎回ifの処理をしなくてはならなくなったわけです。うーん、なんとかグローバル変数の数を減らし、しかもifの処理が一度ですむ方法はないものか。