JSでプライベートコンストラクタを実現する小技

JavaScript は言語レベルでプライベートメソッドをサポートしていないので、プライベートコンストラクタを実現しようとしたら自分で工夫しないといけない。

通常のコンストラクタを隠蔽して、自作の static メソッドからのみインスタンス作成を許すようにするには、いくつかアイデアがある。

プライベートコンストラクタのアイデア1

一番目のアイデアは、モジュールを外に出す出口をいじる。

class Foo {}

const constructors = {
  fromJSON () {
    /** ... */
    return new Foo()
  },
  fromBarClass () {
    /** ... */
    return new Foo()
  }
}

module.exports = constructors

Foo ではなく constructors のほうをエクスポートする。これでモジュール外からは new Foo() できなくなる。

プライベートコンストラクタのアイデア2

二番目のアイデアは、Symbolを使う。クラスをそのままエクスポートできるので一番目のアイデアより汎用性がある。

const PRIVATE_CONSTRUCTOR_SYMBOL = Symbol('private')

class Foo {
  constructor (symbol) {
    if (symbol !== PRIVATE_CONSTRUCTOR_SYMBOL) {
      throw new Error('Not allowed to initialize from outside')
    }
  }

  static fromJSON () {
    /** ... */
    return new Foo(PRIVATE_CONSTRUCTOR_SYMBOL)
  },
  static fromBarClass () {
    /** ... */
    return new Foo(PRIVATE_CONSTRUCTOR_SYMBOL)
  }
}

module.exports = Foo

こうするとモジュール外から new Foo() すると必ず実行時にエラーになる。