JavaScript

JavaScriptでクラスを作るときにprivateをどうするか考えてみた

JavaScriptで自作クラスを作るときに問題となるprivateをどう実装するか、
とりあえずこんな感じだとどうだろう的なものを考えてみた。
ついでに他の言語っぽく変数定義→コンストラクタ→関数の順にも書きたかった。

private変数のあるクラス

例なので、とりあえず
- インスタンス数をprivate staticな変数で持っておいて、public staticな関数で取得
- カウント数をprivateな変数で持っておいて、publicな変数でカウント吸うを増やしたりカウント数を取得したりする
というだけのクラスです。

test.js
(function () {
    'use strict';

    // private static 初期化
    let _instanceCount = 0;

    let Class = function () {
        // public
        let _public = this;

        // private 初期化
        let _count = 0;

        // コンストラクタ
        let _constructor = function () {
            _instanceCount++;
        };

        _public.addCount = function () {
            _count++;
        };

        _public.getCount = function () {
            return _count;
        };

        _constructor();
    };

    // public static
    Class.getInstanceCount = function () {
        return _instanceCount;
    };
}());

補足

  • 実際には、ClassmyApp.Classのような名前空間を作ってそこに代入して使う想定。
  • public staticを下にしかかけないのが辛い
  • 書いた本人は言語仕様に詳しくないのでもっと良い書き方があると思う

追記

- WeakMapを使った場合は以下のような感じ

test.js
(function () {
    'use strict';

    // WeakMap
    let _weakMap = new WeakMap();

    let _getPrivate = function(object) {
        let map = _weakMap.get(object);
        if(map === null) {
            map = {};
            _weakMap.set(object, map);
        }
        return map;
    }

    // private static 初期化
    let _instanceCount = 0;

    let Class = function () {
        // public
        let _public = this;

        // private 初期化
        let _private = getPrivate(this);

        // コンストラクタ
        let _constructor = function () {
            _instanceCount++;
            _private.count = 0;
        };

        _public.addCount = function () {
            _private.count++;
        };

        _public.getCount = function () {
            return _private.count;
        };

        _constructor();
    };

    // public static
    Class.getInstanceCount = function () {
        return _instanceCount;
    };
}());

JavaScriptのclassも、classを使わずにこういう書き方するのもあまり好きじゃない・・・