コードの再利用方法をメモしておく

JavaScriptにおけるコードの再利用方法には下記などがある。

  • 単なる呼び出し
  • メソッドの拝借
  • コンポジション
  • ミックスイン
  • プロトタイプ継承
  • (擬似)クラス継承

メソッドの拝借

全ての関数オブジェクトがもつメソッドである call あるいは apply を用いる。
呼び出したい関数の call や apply メソッドを下記のように呼び出すことで、 obj を this として当該メソッドを呼び出すことができる。
call(obj, arg1, arg2, ..)
apply(obj, [arg1, arg2, ..])
例:配列のメソッドを拝借する(※argumentsは擬似配列であるため)

Array.slice.call(arguments, 1, 5);

コンポジション

利用したいオブジェクトをフィールドとしてもつ。
例:文字列だけを格納できる配列

function createStringArray() {
	var array  = [];
	return {
		add: function(obj) {
			if(obj instanceof String) {
				array.push(obj);
			}
		},
		get: function(i) {
			return array[i];
		}
	};
}

ミックスイン

複数のオブジェクトからプロパティをコピーして組み合わせる。
例:ミックスイン関数(※浅いコピーの例)

function mix() {
	var mixed = {};
	for(var i = 0, arglen = arguments.length; i < arglen; i++) {
		var arg = arguments[i];
		for(var prop in arg) {
			if(arg.hasOwnProperty(prop)) {
				mixed[prop] = arg[prop];
			}
		}
	}
	return mixed;
}

プロトタイプ継承

  • プロトタイプオブジェクトの位置づけ
    • すべてのオブジェクトは、プロトタイプオブジェクトへの参照をもつ
    • すべての関数は、プロトタイプオブジェクトのデフォルトとして{constructor:<その関数自身>}をもつ
    • コンストラクタで初期化されたすべてのオブジェクトは、コンストラクタのプロトタイプオブジェクトのメンバを(プロトタイプチェーンを辿った末に)読み取り専用で参照することができる。(※それゆえ、いわゆるStaticなメンバはプロトタイプオブジェクトに定義するとよい)
  • プロトタイプオブジェクトを格納するメンバの物理名
    • 関数の場合、prototype
    • 関数以外のオブジェクトの場合、__proto__ (※Firefoxなどでは参照できるが、一般には参照できない)

例:

var Child  = function(){};
Child.prototype = {info:{role:'親'}};
var child = new Child();
alert('child.info.name:'+child.info.name);

// Firefoxなどでは下記も可能
child.__proto__ = {info:{role:'親'}};

(擬似)クラス継承

色々考慮したら、クラス継承関数は下記のようになるらしい。難しい。。

function inherit = (function() {
	var F = function(){};
	return function(Child, Parent) {
		F.prototype = Parent.prototype;
		Child.prototype = new F();
		Child.uber = Parent.prototype;
		Child.prototype.constructor = Child;
	}
}());

YUIライブラリなど各種ライブラリがこれと同様の機能を用意しているとか。
確かに、プロトタイプ継承で不便ないならこのトリッキーな方法はとりたくないなぁ。

参考文献