JavaScriptにおける関数型コンストラクタ

どうもこんばんは、south37です。前回の続きとして、jsにおける「関数型コンストラクタ」とはなんぞや、ってところから書き始めたいと思います。参考にしてるのはやっぱりJavaScript-The-Good-Partsです。

関数型コンストラクタ

関数型コンストラクタは、簡単にいえばオブジェクトを返す関数です。jsのnewがあまりにもクソだから極力使いたくなくて、代わりに関数型コンストラクタを使おうって事らしいです。まずは概念をコードで示してみます。

var constructor = function (spec) {
  var that;
  その他のインスタンスプライベート変数もここで宣言

  that = 新しいオブジェクト;

  メソッドをthatに追加

  return that;
}

仕組みは単純で、thatオブジェクトを生成した後、メソッドを追加してからreturnするだけです。注目すべきは、メソッドを追加する際にクロージャを利用して変数のカプセル化を行っている事でしょうか。これにより、擬似的なプライベート変数を作る事が出来ます。これが最大のメリットと言えます。
ちなみに、コンストラクタの引数のspecは「仕様(specification)」という意味で、オブジェクト初期化に必要な情報をためこんだコンテナです。

関数型コンストラクタを用いた具体的な例を示してみます。

var mammal = function (spec) {
  var that   = {},
      name   = spec.name,
      saying = spec.saying;

  that.get_name = function () {
    return name;
  };

  that.says = function () {
    return saying;
  };

  return that;
};

var myMammal = mammal({
  name:   'Herb',
  saying: 'meow'
});

console.log(myMammal.name);        //undefined
console.log(myMammal.get_name());  //Herb

myMammalのnameがカプセル化されているのが分かるかと思います。

superiorメソッド

関数型コンストラクタを用いる際、、Objectクラスのprototypeを拡張してsuperiorメソッドというものを定義する事で、継承元のメソッドの呼び出しも行えるようになります。

Object.method('superior', function (name) {
  var that = this,
      method = that[name];

  return function () {
    return method.apply(that, arguments);
  };
});

var mammalBaby = function (spec) {
  var that = mammal(spec),
      super_get_name = that.superior('get_name');

  that.get_name = function () {
    return 'like ' + super_get_name() + ' baby';
  };

  return that;
}

var myMammalBaby = mammalBaby({
  name:   'Herb',
  saying: 'meow'
});

console.log(myMammalBaby.get_name());  //like Herb baby

継承元のmammalに存在したget_nameを利用しながら、get_nameを上書きしています。ポイントは、super_get_nameという名前をつけて継承元のget_nameへの参照を残している点です。クロージャを上手く利用しているといえます。

今日はここまでです!