JavaScript Good Parts
JavaScript Good Partsという本を読んでます。
JavaScriptを無免許運転してきた僕には、かなり勉強になってます。Javaのような静的型付け言語から来ると、目から鱗っぽいです。
第四章FunctionsのModuleの説明に、こんなサンプルコードが出てきます。
1 var serial_maker = function () {
2 // Produce an object that produces unique strings. A
3 // unique string is made up of two parts: a prefix
4 // and a sequence number. The object comes with
5 // methods for setting the prefix and sequence
6 // number, and a gensym method that produces unique
7 // strings.
8
9 var prefix = '';
10 var seq = 0;
11 return {
12 set_prefix: function (p) {
13 prefix = String(p);
14 },
15 set_seq: function (s) {
16 seq = s;
17 },
18 gensym: function () {
19 var result = prefix + seq;
20 seq += 1;
21 return result;
22 }
23 };
24 };
25 var seqer = serial_maker();
26 seqer.set_prefix('Q');
27 seqer.set_seq(1000);
28 var unique = seqer.gensym(); // unique is "Q1000"
(JavaScript Good Parts P41-42より引用
25行目で、function serial_makerを実行すると、変数seqerには行11から行23で定義されたオブジェクトが返され代入されます。この時点で変数seqerからは、function serial_makerが見えなくなります。でも行26,27でset_prefix,set_seqメソッドの中で、変数prefix,seqにアクセスしています。これはクロージャーが可能にしています。
こういう風に書くと何が良いかを、JavaScript Good Partsでは以下のように説明してます(意訳です)。
...で、seqerを誤摩化して悪いことができなくします。seqerに定義されたメソッドを通さないで、変数prefix、seqにアクセスすることは出来ません。seqerオブジェクトはミュータブルですから、メソッドを置き換えることはできます。しかし、置き換えたメソッドからは変数prefix,seqにアクセスすることはできません。
(JavaScript Good Parts P42より意訳
アクセスできないのは、置き換えるメソッドはserial_maker functionの外で定義されるので、クロージャーの外になっちゃうから、、という理解で良いのかな。オブジェクト指向の一つの考え方『隠蔽化』をJavaScriptでやるとこんな風になるわけ、と目から鱗でした。