よく使うパターン
あんまり意味のないHelloクラスを定義してみる
var Hello = (function(){
// constructor
function Hello(name){
this._name = name;
}
// private method
function say(message){
console.log(message + ', ' + this._name);
}
// public method
function hello(){
say.call(this, 'Hello');
}
Hello.prototype = {
// constructor 修正
constructor: Hello,
// 以下 public メソッド
hello: hello
};
return Hello;
}());
このパターンのポイントは、即時関数内にクラスに関係あるメソッドや変数をまとめるところ。
クラスの定義以外は、即時関数の外を汚さない。
また、公開したいインターフェースは最後のprototype
に列挙するだけでいいのもポイント高い。
継承
このパターンで継承する場合ちょっとややこしくなる。
というかJSで継承しようとするとややこしくなる。
var Animal = (function(){
function Animal(name){
this._name = name;
}
function say(){
throw new Error('not implemented');
}
Animal.prototype = {
constructor: Animal,
say: say
};
return Animal;
}());
var Dog = (function(){
function Dog(name){
// super call
Animal.call(this, name);
}
function say(){
console.log('bowwow');
}
// Animal.prototype をプロトタイプチェーンに追加したいが、コンストラクタが邪魔なのでちょっと細工する
Dog.prototype = (function(){
function F(){}
F.prototype = Animal.prototype;
return new F();
}());
// 複数メソッドを定義する場合、並べて書かないとダメなのであまりイケてない
Dog.prototype.constructor = Dog;
Dog.prototype.say = say;
return Dog;
}());
Object.create
が使えるなら
ちょっとスマートに書ける
var Animal = (function(){
function Animal(name){
this._name = name;
}
function say(){
throw new Error('not implemented');
}
Animal.prototype = {
constructor: Animal,
say: say
};
return Animal;
}());
var Dog = (function(){
function Dog(name){
// super call
Animal.call(this, name);
}
function say(){
console.log('bowwow');
}
// すっきり!
Dog.prototype = Object.create(Array.prototype);
// でもここはやっぱりイケてない
Dog.prototype.constructor = Dog;
Dog.prototype.say = say;
return Dog;
}());