LoginSignup
2
3

More than 5 years have passed since last update.

JavaScriptでprivateっぽいことやってみた

Last updated at Posted at 2015-10-22

JavaScriptにはprivateみたいな機能がない

  1. インスタンスごとに生成される、外からアクセスできない変数を作りたいとする
  2. その変数にアクセスするメソッドをインスタンスが生成されるたびに定義するのはメモリの無駄なのでprototypeに突っ込みたいとする
  3. 1.をやるためには、変数宣言をfunction Class(){ 〜 }の中でやらなきゃいけない
  4. 2.をやるためには、メソッドをfunction Class(){ 〜 }の外でやらなきゃいけない
  5. クロージャ的に届かない

→プライベートメンバは無理!

参考: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は無理だと散々言われているので、この方法が大丈夫か不安。
そもそも構文として存在しないなら、無理に実現しなくてもいいのかなーとも思う。
何か間違っているところがあればご教授願います。

2
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3