JavaScriptにはprivateみたいな機能がない
- インスタンスごとに生成される、外からアクセスできない変数を作りたいとする
- その変数にアクセスするメソッドをインスタンスが生成されるたびに定義するのはメモリの無駄なので
prototype
に突っ込みたいとする - 1.をやるためには、変数宣言を
function Class(){ 〜 }
の中でやらなきゃいけない - 2.をやるためには、メソッドを
function Class(){ 〜 }
の外でやらなきゃいけない - クロージャ的に届かない
→プライベートメンバは無理!
参考:Javascriptでプライベートメンバを使うなら、prototypeは諦める - 部屋とボードゲームと私と酒と泪と男と女
違った方法で実現してみる
数をインクリメントするオブジェクトを例にとってみます。英語がおかしいかもしれないですが。
var Counter = (function() {
// プライベートメンバを保存する場所
var privates = [];
// プライベートメンバを取得する関数
function privateOf(instance) {
// インスタンスをキーにして取得して返す
for (var i = 0; i < privates.length; i++) {
if (privates[i].key === instance) {
return privates[i].value;
}
}
// 無かったら生成して返す
var value = {};
privates.push({
key: instance,
value: value
});
return value;
}
// コンストラクタ
function Counter() {
privateOf(this).count = 0;
}
// ちゃんとprototypeから使える
Counter.prototype.increment = function() {
return ++privateOf(this).count;
};
return Counter;
})();
var c1 = new Counter();
var c2 = new Counter();
// ちゃんとバラバラに動く
c1.increment(); // 1
c1.increment(); // 2
c2.increment(); // 1
// アクセスしようがない
c1.count; // undefined
メリット
- ちゃんとインスタンスごとに生成される
- 外からアクセスできない
-
prototype
にメソッドを突っ込んでもそこから使える
デメリット?
- 上記の
privateOf
みたいなくだりをいちいち書くのが面倒臭い。この辺うまく関数化してまとめた方がいいかも。 - 関数で取得する形なので機能的な実現はできたが構文的な再現はできていない。プライベート変数というよりオブジェクト。
- 即時関数の外からメソッドを新しく定義したい場合はアクセスできない。まあそれは当たり前か。
所感
既出だったらすみません。
何よりJavaScriptでprivateは無理だと散々言われているので、この方法が大丈夫か不安。
そもそも構文として存在しないなら、無理に実現しなくてもいいのかなーとも思う。
何か間違っているところがあればご教授願います。