JavaScript: クラスの Tips - メソッドチェーン / ファクトリーメソッド / クラス名でインスタンス化

JavaScript: クラスの Tips - メソッドチェーン / ファクトリーメソッド / クラス名でインスタンス化

February 24, 2022

this を返すようにするとメソッドチェーンで書けるので便利 #

class Calculator {
  #number;

  constructor(initial = 0) {
    this.#number = initial;
  }

  print() {
    console.log(this.#number);
  }

  add(num) {
    this.#number += num;
    return this;
  }

  subtract(num) {
    this.#number -= num;
    return this;
  }

  multiply(num) {
    this.#number *= num;
    return this;
  }

  divide(num) {
    this.#number /= num;
    return this;
  }
}
new Calculator(9).add(5).subtract(4).multiply(3).divide(2).print(); // 15

new を書きたくないならファクトリーメソッドを用意すると便利 #

以下では of というメソッド名にしています。

class Calculator {
  #number;

  constructor(initial = 0) {
    this.#number = initial;
  }

  static of(initial = 0) {
    return new this(initial);
  }

  print() {
    console.log(this.#number);
  }

  add(num) {
    this.#number += num;
    return this;
  }

  // ...後略
}
Calculator.of(11).add(6).subtract(5).multiply(4).divide(3).print(); // 16

クラス名だけでインスタンス化したいならばこうすると便利 #

Number(9)Array(3) のようにクラス名をそのままコンストラクタのように使ってインスタンスを作ることは、クラス宣言では実現できませんが、関数宣言であれば実現可能です。

function Calculator(initial = 0) {
  if (!(this instanceof Calculator)) {
    return new Calculator(initial);
  }

  this._number = initial;

  this.print = function () {
    console.log(this._number);
  };

  this.add = function (num) {
    this._number += num;
    return this;
  };

  // ...後略
}
Calculator(15).add(7).subtract(6).multiply(5).divide(4).print(); // 20

まとめ #

上記すべてを1つで実現させると以下になります。

const Calculator = (function () {
  function CalculatorBase(initial = 0) {
    if (!(this instanceof CalculatorBase)) {
      return new CalculatorBase(initial);
    }

    this._number = initial;

    this.print = function () {
      console.log(this._number);
    };

    this.add = function (num) {
      this._number += num;
      return this;
    };

    this.subtract = function (num) {
      this._number -= num;
      return this;
    };

    this.multiply = function (num) {
      this._number *= num;
      return this;
    };

    this.divide = function (num) {
      this._number /= num;
      return this;
    };
  }

  CalculatorBase.of = function (initial = 0) {
    return new this(initial);
  };

  return CalculatorBase;
})();
new Calculator(9).add(5).subtract(4).multiply(3).divide(2).print(); // 15

Calculator.of(11).add(6).subtract(5).multiply(4).divide(3).print(); // 16

Calculator(15).add(7).subtract(6).multiply(5).divide(4).print(); // 20