tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

javascriptのクロージャについておさらいメモ

はじめに

javascriptのクロージャって毎回わかったようでわかってないorz
そんな自分のためのおさらい&理解メモ

こんな流れで理解を深めよーと思います

1.クロージャとは
2.実際どんなの?
3.メリット①(データ (環境) をそれを操作する関数と結びつける)
4.メリット②(プライベートメソッドを模倣する)
5.よくある間違い(ループ内でクロージャを生成)

もし見る方がいたらこちらも見てもらえるともっとわかりやすいかと
javascriptのscope(スコープ)をおさらいメモ

クロージャとは

wikiさんの言葉をそのまま拝借します。

関数閉包はプログラミング言語における関数オブジェクトの一種。
引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決することを特徴とする。

ふむふむ…文章だと素直に難しいですね。。汗


「クロージャとは」の説明ではないですが
自分なりにも語弊を恐れないで書いてみます

javascriptのクロージャは
スコープチェーンとその検索プロセスから生成される

そのスコープチェーンと検索プロセスについては
こちらで書いたのでそっちから見るとわかりやすいかも

2.実際どんなの?

ってことでソースでも書いてみます
簡単なクロージャ例

gとfを実行すると
両方ともfunction() { console.log(x); };な感じの関数を実行するはずですが結果は違います。
これはfがクロージャだからです。
関数定義時に生成されたスコープを保持したままになっているので変数xにアクセスできています。

よくある感じのソースですが自分がいつも理解したつもりで忘れてしまうのは、
「ふんふん、わかった」と読んだんだソースはわかっても

  • これをどう使うのか
  • メリットはなんなのか

などなどまで深く理解してないからだなーと思い今回その辺を重点的に書いてみることにしました

また、ここからはだいたいMDNさんの記事を参考にさせて頂きました!

3.メリット①(データ (環境) をそれを操作する関数と結びつける)

「データ (環境) をそれを操作する関数と結びつける」っていう文章がまたアレですが、ここは自分なりに言うと
「プライベート変数を作れる」と理解しました
※こちらも語弊があったらご指摘お願いします(>_<)

3-1.ってことでソースで確認


コメントに書きましたが、データcとreturnで返される無名関数を結びつけた感じです
変数cには外部からアクセスできないのでプライベートっぽくなっています


また、データ (環境)ということも理解するためにソースをちょっと変えてみます

3-2.こちらもソースで確認


これを見るとわかるとおり、クロージャ環境は個々に作成できます
共有であれば11行目のfunc5()によって最後のfunc1();は「5」と出力されそうですが結果は「1」と表示されます

4.メリット②(プライベートメソッドを模倣する)

こちらはまんまMDNさん記事のソースを使わせてもらいました
※わかりやすすぎて(>_<)

ソースで確認


privateCounter、changeByがprivateなメンバです。
無名関数の外からはアクセスできませんが、
プライベートオブジェクトのメソッドからはアクセスできます。


5.よくある間違い(ループ内でクロージャを生成)

こちらもMDNさんのパクリですが、js単体で動くようにソース変えてみました

間違ったソース


memberにsayという関数を追加しています。
9行目の変数memberへの参照を持ったクロージャです。

期待する結果は001、002、003と出力されることですが、
実行結果はすべて「i am 003」となってしまいます

これは、
15行目でvar members = createMembers();と1回実行することで
sayクロージャは3つ生成されましたが、
10行目の関数定義とcreateMembers関数のスコープから補足された1つのクロージャ環境を共有しているためです


3-2では違う環境のクロージャが生成できました。
3.2との違いは、クロージャを生成する関数が3回実行されたか、1回実行されたかということになります。
ということは、1回の実行で1回のクロージャ環境と理解すれば良いかもしれないですね。
※かなり文章に自信ないですがご指摘待ちで書いてます(><)


ってことで、これを修正して期待通りにするには
呼び出しは1回のままで、内部でクロージャーを生成する関数が3回実行されれば良いわけです

ということで修正したソース


書いてはみたものの説明するとやっぱり難しい(^^;

自分的にも最後がなんか歯切れ悪い文章になってしまいましたが、
一応理解は深まったんではないか(たぶん…)ということでクロージャメモでした!

この記事で参考にした書籍

開眼!  JavaScript ―言語仕様から学ぶJavaScriptの本質
Cody Lindley
オライリージャパン
売り上げランキング: 11,609