[Javascript] Javascriptにおけるメンバ変数の隠蔽(カプセル化)

こんばんわ。
プチ花見のおじいさんです。花咲じいさんではありませんが、ゆさゆさゆすって、桜をちらしておりました。
若干酔ってます酔ってます。
で、今日のお題はJavascriptにおけるメンバ変数の隠蔽というか、private変数の作り方についてです。

まあ、Javascriptは一般にはprivate変数がない、つまりカプセル化できないと思っていたんですが、同じように言われていたPerlでそれができるわけです。
ということは同じ仕組みを使えば、隠蔽できるんじゃねえのかと思いました。
Googleとかで探してみると、結構記事がありますね。

お爺さんのやった方法は以下の通り。


<html>
<body>
クロージャを利用した隠蔽化<br>
<script>

function SimpleObj() {}
var obj = new SimpleObj();

SimpleObj.prototype = {
  get_num : null,
  set_num : null,
  add_num : null,
  create : function() {
    var num; // private変数
    this.get_num = function() {return num};
    this.set_num = function(num1) {num=num1};
    this.add_num = function(num1) {num+=num1};
  }
};

var o1 = new SimpleObj();
o1.create();
o1.set_num(1);
o1.add_num(1);
o1.add_num(1);
o1.add_num(1);
o1.add_num(1);
o1.add_num(1);

var o2 = new SimpleObj();
o2.create();
o2.create();
o2.set_num(10);
o2.add_num(10);
document.writeln("o1.get_num()="+o1.get_num()+"<br>");
document.writeln("o1.num="+o1.num+"<br>");
document.writeln("o1.create.num="+o1.create.num+"<br>");
document.writeln("o2.get_num()="+o2.get_num()+"<br>");
document.writeln("o2.num="+o2.num+"<br>");
document.writeln("o2.create.num="+o2.create.num);


</script>
</body>
</html>


実行結果を見ていただければわかるんですが、o1.numとしても、o1.create.numとしても、アクセスできていません。createのauto変数だからです。
これにアクセスするには、クロージャを定義してやって、そのクロージャをアクセサとして登録してやる、という作業になります。
そのアクセサ越しにしか触れないので、実質private変数ができちゃったー、という事です。

で、これをじっと見ていたんですが、PerlのInside-Outオブジェクトとはちょっと違いますね。
Perlの場合は、このnumにあたるものがオブジェクトの外にあるんですが、この場合は中にありますから。
やっぱりクロージャ(閉包)を利用したprivate変数の作り方、というのが正しいですね。

#04/06 01:11若干色々変更してみた。
private変数と言うんだから、private関数から扱えないと駄目だろうとそれも作ってみた。
それからpublic変数もちょっとさわってみる。public変数はthis.xxxとしないと駄目ですね。
少しごちゃごちゃしてきたかな・・・


<html>
<body>
クロージャを利用した隠蔽化<br>
<script>

function SimpleObj() {}
var obj = new SimpleObj();

SimpleObj.prototype = {
  create : function() {
    var num; // private変数
    mypublic = {
      // public 変数
      M : 0,
      // public 関数
      set_M : function(num1) {mypublic.M = num1},
      get_num : function() {return num},
      set_num : function(num1) {num=num1},
      add_num : function(num1) {num+=num1},
      times_num : function(num1) {_times(num1)},       // private funcを呼び出す
      times_M : function() {num*=this.M;alert(this.M)} // public変数を使う。mypublic.Mではなく、this.M
    };
    var _times = function(num2) { // private 関数
      num*=num2;
      mypublic.add_num(1);     // public funcを呼び出す
    };
    for (var p in mypublic) { this[p] = mypublic[p] };//publicな変数や関数を設定
  }
};

var o1 = new SimpleObj();
o1.create();
o1.set_num(1);
o1.add_num(1);
o1.add_num(1);
o1.add_num(1);
o1.add_num(1);
o1.add_num(1);
o1.M = 2;
o1.times_M(1);

var o2 = new SimpleObj();
o2.create();
o2.create();
o2.set_num(10);
o2.add_num(10);
o2.times_num(10);
document.writeln("o1.get_num()="+o1.get_num()+"<br>");
document.writeln("o1.num="+o1.num+"<br>");
document.writeln("o1.create.num="+o1.create.num+"<br>");
document.writeln("o2.get_num()="+o2.get_num()+"<br>");
document.writeln("o2.num="+o2.num+"<br>");
document.writeln("o2.create.num="+o2.create.num);
</script>
</body>
</html>


で、これを継承すると一体どうなるんだろ?
protectedな変数とか作れるんだろうか?
ちょっと調べてみたいもんです。

ブログ気持玉

クリックして気持ちを伝えよう!

ログインしてクリックすれば、自分のブログへのリンクが付きます。

→ログインへ

なるほど(納得、参考になった、ヘー)
驚いた
面白い
ナイス
ガッツ(がんばれ!)
かわいい

気持玉数 : 0

この記事へのコメント

この記事へのトラックバック