JavaScriptのオブジェクト指向について自分メモを書いてみたとか〜

■基本編
忘れないうちに・・・っと。
(2012-01-16)
・④を訂正しました。


①基本

function Class(value){                          //コンストラクタ
  this.property=value;                          //インスタンスプロパティ
  this.method=function(){alert(this.property);}  //インスタンスメソッド
}

var c=new Class(value); //インスタンス生成
// c.property; プロパティ利用
// c.method(); メソッド利用

ここでthisでなくてvarじゃだめなのか。と思って調べると
ここ(第101回 JavaScriptで関数をクラスのように使うとき 中にvarと書くかthisと書くかそれが問題だ - bingo_nakanishiの他言語出身者のためのPerl入門)で解説ありました。


②prototypeを使用
上のままではインスタンスごとにメソッド(同じコード)が増える=無駄
また、静的なプロパティ・メソッドもあるので次のようにする

function Class(value){
  this.property=value;                                  //インスタンスプロパティ
}
Class.PROPERTY=VALUE;                                    //クラスプロパティ
Class.METHOD=function(){alert(Class.PROPERTY);}          //クラスメソッド(this.〜プロパティは使えない)
Class.prototype.method=function(){alert(this.property);} //インスタンスメソッド(this.〜が使える)

ここでインスタンスメソッドが複数の場合に記述が面倒


③オブジェクトリテラルの記述で

var obj={
  property1:value1,
  property2:value2,
  method1:function(){},
  method2:function(){},
 ・・・
}
        ↑↓
obj.property1=value1;
obj.property2=value2;
obj.method1=function(){};
obj.method2=function(){};

を利用して

function Class(value1,value2){
  this.property1=value1;
  this.property2=value2
}
Class.PROPERTY=VALUE;
Class.METHOD=function(){alert(Class.PROPERTY);}
Class.prototype={
  method1:function(){alert(this.property1);},
  method2:function(){alert(this.property2);}
}



④またはこれを使って

function func(value){}
      ↑↓
var func=function(value){}


var Class=function(value1,value2){
  this.property1=value1;
  this.property2=value2;
}
Class.PROPERTY=VALUE;
Class.METHOD=function(){alert(Class.PROPERTY);}
Class.prototype={
  method1:function(){alert(this.property1);},
  method2:function(){alert(this.property2);}
}



■継承編
(2012-01-16)
・⑤をわかりやすくしました。


継承には普通に
・プロパティ: コンストラクタチェーン(call,apply)
・メソッド : プロトタイプチェーン(prototype)
を使います。
ここから始めます。

function SuperClass(value1,value2){
  this.property1=value1;
  this.property2=value2
}
SuperClass.prototype={
  method1:function(){alert(this.property1);},
  method2:function(){alert(this.property2);}
}



①callを使用(コメントについては以下同様)

function SubClass(value1,value2,value3){
  SuperClass.call(this,value1,value2);
  this.property3=value3; //SubClass追加のプロパティ
}
SubClass.prototype=new SuperClass();
SubClass.prototype.method2=function(){alert(this.property2+'sub');} //オーバーライド
SubClass.prototype.method3=function(){alert(this.property3);} //SubClass追加のメソッド



②applyを使用

function SubClass(value1,value2,value3){
  SuperClass.apply(this,[value1,value2]);
  this.property3=value3;
}
SubClass.prototype=new SuperClass();
SubClass.prototype.method2=function(){alert(this.property2+'sub');}
SubClass.prototype.method3=function(){alert(this.property3);}



③ここでprototypeを書くのが面倒。でもprototype=でまとめると
 最初のSubClass.prototype=new SuperClass()を上書きしてしまい継承されないw
 ということで調べると
 こちら(JavaScript, apply/call メソッドと prototype 継承 : Serendip – Webデザイン・プログラミング)にありました。
 上記に当てはめると・・・

function SubClass(value1,value2,value3){
  SuperClass.apply(this,[value1,value2]);
  this.property3=value3;
}
SubClass.prototype=new SuperClass();
(function(){
  this.method2=function(){alert(this.property2+'sub');}
  this.method3=function(){alert(this.property3);}
}).apply(SubClass.prototype);



④だけどthisも面倒だなあ・・・と思って調べているといろいろありました。
 ひとつめ。newを封印して、JavaScriptでオブジェクト指向する(1): Architect Note
 ふたつめ。JavaScript におけるクラスの作成と継承 - vivid memo
 ついていけませんw今回はそこまで必要としないので。


⑤他の言語のような見易さを考えた結果こうしてみました。
・Function(関数ビルトインオブジェクト)のprototypeにextendメソッドを追加(1回だけ)

Function.prototype.extend=function(SuperClass,subMethod){
  this.prototype=new SuperClass();//Superクラスのprototypeメソッドチェーン設定
  for(name in subMethod){
    this.prototype[name]=subMethod[name];//追加メソッド・オーバーライド分をコピー
  }
}

・あとはこういう形で記述できます。

function SubClass(value1,value2,value3){
  SuperClass.apply(this,[value1,value2]);
  this.property3=value3;
}
SubClass.extend(SuperClass,{
  method2:function(){alert(this.property2+'sub');},
  method3:function(){alert(this.property3);}
});



(収穫)
・今回の件でこんなこともできると知りました。

Function.prototype.hyouji=function(mes){
  alert("Hello "+mes);
}
var a=function(){}.hyouji("world!");
        ↑↓
function b(){}
b.hyouji("work!");

・ただしこんなことはできませんでした。

Function.prototype.METHOD=function(){
  alert("Hello");
}

function Class(){}

var instance=new Class();//Classのインスタンス
instance.METHOD();//エラー(METHODはクラスメソッド扱い?)