オライリーの「JavaScriptパターン」で、コンストラクタを使って生成したインスンタンスでプライベートメンバ(プロパティ)を実現する方法が2つほど紹介されている。
- P98. 「5.3.5 プロトタイプとプライバシー」
- P103. 「5.4.2 コンストラクタを作成するモジュール」
この「プライベートメンバ(プロパティ)」は、 Java でいうところのインスタンス変数ではなく、クラス変数と同じ振る舞いをする。
本をよく読むと、確かに以下のように書いてある。
- P98
この方法によって同じコンストラクタで作成されたインスタンスはすべて 共通する部分を共有できる ようになります。
危うくインスタンス変数だと勘違いしたまま使うところだった。。。
#検証
##「5.3.5 プロトタイプとプライバシー」で紹介されている方法
サンプル:http://jsfiddle.net/opengl_8080/CRG7P/
function MyClass(name) {
this.name = name;
}
MyClass.prototype = (function(){
var message;
return {
getMessage: function() {
return this.name + '「' + message + '」';
},
setMessage: function(value) {
message = value;
}
};
}());
var hoge = new MyClass('hoge');
hoge.setMessage('嘘だ・・・インスタンス変数だろ・・・これ・・・インスタンス変数に決まってる・・・!');
console.log(hoge.getMessage());
var fuga = new MyClass('fuga');
fuga.setMessage('ところがどっこい・・・インスタンス変数じゃありません・・・! クラス変数です・・・! これが現実・・・!');
console.log(hoge.getMessage());
hoge「嘘だ・・・インスタンス変数だろ・・・これ・・・インスタンス変数に決まってる・・・!」
hoge「ところがどっこい・・・インスタンス変数じゃありません・・・! クラス変数です・・・! これが現実・・・!」
##「5.4.2 コンストラクタを作成するモジュール」で紹介されている方法
サンプル:http://jsfiddle.net/opengl_8080/r4FFR/
var MyClass = (function(){
var _message;
var Constr = function(name) {
this.name = name;
};
Constr.prototype = {
setMessage: function(message) {
_message = message;
},
getMessage: function() {
return this.name + '「' + _message + '」';
}
};
return Constr;
}());
var hoge = new MyClass('hoge');
hoge.setMessage('もしかしてクラス変数ですかーッ!?');
console.log(hoge.getMessage());
var fuga = new MyClass('fuga');
fuga.setMessage('YES! YES! YES! "OH MY GOD"');
console.log(hoge.getMessage());
hoge「もしかしてクラス変数ですかーッ!?」
hoge「YES! YES! YES! "OH MY GOD"」
#じゃあ、どうすればプライベートなインスタンスメンバを定義できるのか?
##インスタンスの数が少ないことが予想される場合
→ コンストラクタ関数にプライベートメンバも特権メソッドも全部書く。
function MyClass() {
var privateMember;
this.getPrivateMember = function() {
return privateMember;
};
}
##インスタンス数が多くなることが予想される場合
→ 諦めて全部 public にする。
そもそも、言語仕様で private がサポートされてないのだから、潔く全部 public にすべきなのかもしれない。
#参考