LoginSignup
1
0

More than 3 years have passed since last update.

JavaScript でコンストラクタをプライベートにする

Posted at

はじめに

  • コンストラクタを不可視にしたい
  • 即時関数でもできるが、読みづらいので他の方法を考えてみた
  • 可視性の境界をモジュール単位にするのがシンプルっぽい

やりかた

インスタンスを生成する関数だけエクスポートする。

Point.js
class Point {
  constructor (x, y) {
    this.x = x
    this.y = y
  }
}

// ファクトリーメソッド
function pointAt(x, y) {
  return new Point(x, y)
}

// ファクトリーメソッドだけ export する
export { pointAt }
利用側
import { pointAt } from './Point.js'

let p = pointAt(0, 1)

使いどき

インスタンスの生成方法を強制したいとき。
Java の Integer クラス のように、頻繁に使われれる値オブジェクトをキャッシュするときなど。

2次元平面上の座標を表す Point クラスを考えます。xy の値を保持するだけのクラスです。同値判定を簡単に行うため、同じ座標の場合は常に同じオブジェクトの参照を返すようにしています。

Point.js
class Point {
  constructor (x, y) {
    this.x = x
    this.y = y
  }
}

// インスタンスを格納しておくマップ
const cache = {}

// ファクトリーメソッド
// 同じ x, y の組み合わせは常に同じインスタンスを返す
function pointAt (x, y) {
  let key = x + ':' + y
  if (key in cache) {
    return cache[key]
  } else {
    let instance = new Point(x, y)
    cache[key] = instance
    return instance
  }
}

export { pointAt }
利用側
import { pointAt } from './Point.js'

let p1 = pointAt(1, 2)
let p2 = pointAt(1, 2)

p1 === p2 // これが true を返すので、プリミティブな値のように扱える

Array.includes は参照での比較を行うためプリミティブな値でしか使えませんが、このファクトリーメソッドで生成した Point は同じ値は同じインスタンスなのでそのまま使えます。

利用例
import { pointAt } from './Point.js'

let arr = [pointAt(0, 1), pointAt(0, 2)]

let target = pointAt(0, 2)
arr.includes(target) // true を返す
1
0
0

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
1
0