サイ本読書記 9章 クラスとコンストラクタとプロトタイプ(後半

プロトタイプオブジェクトは、前半で示したようなユーザー定義クラスだけでなく、組み込みクラスにも継承されている。そして、そこにプロパティを追加する事もできる。
ただし、他の人がさわった時に混乱するので、普通はやらない。例外として、古いブラウザに対応するために使う事はある。

また、Object.prototypeは全てのクラスに影響を及ぼすので、プロパティの追加は絶対に行わない事(とサイ本曰く)。

オブジェクトとプロトタイプのまとめ

オブジェクト

名前がついたデータを、格納するもの。
データと聞くとメソッド(というか関数)は含められなさそうな気がするけど、含められる。JSは関数もデータ。
オブジェクトでもって関連した値やメソッドをひとまとめにする事で、プログラミング作業の効率を上げる事ができる。
JAVAC++は強く型付けされた言語なのでプロパティはあらかじめ定義されていてデータ型も決められている。
JSはその辺が自由で、動的に変更する事もできる。

クラス(のようなもの)(コンストラクタ関数とプロトタイプオブジェクト

クラス(コンストラクタ関数)はオブジェクトの設計図のような物で、コンストラクタ関数を使って生成されたオブジェクトは、そのコンストラクタのインスタンスであると言える。
プロトタイプオブジェクトは全てのオブジェクトから参照される。そしてプロトタイプオブジェクトのプロパティは、全てのオブジェクトに継承される。
コンストラクタ関数でプロトタイプを使うと、そこから生成される全てのインスタンス(オブジェクト)に共有したプロパティが生成される。


JAVAの用語をJavaScriptに無理やりあてはめた説明

(この辺、本当に無理やりな気がするんですけど、実際に使ったりするんでしょうか? 呼び名は無理やりでも、実際のコードしては便利なのかな。
あと、サイ本のサンプルコードは省略された物しかなかったので、自分なりに補って書いてみました。 超自信ない><)

インスタンスプロパティ

インスタンス(コンストラクタ関数によって生成されたオブジェクト)の持つプロパティの事。
コンストラクタ関数を使って生成されたオブジェクトが10個あれば、それぞれに存在する。
それぞれのオブジェクトを介して各インスタンスプロパティにアクセスする事ができる。

function Rect(w,h) {
 this.width = w;
 this.height = h;
}

var rec1 = new Rect(5,10);
var rec2 = new Rect(99,999);

rec1.width 〜
rec2.width 〜

rec1、rec2オブジェクトそれぞれのインスタンスプロパティへのアクセス

この仕組みはJSが少し特殊で、従来のクラスベースのオブジェクト指向言語では、また理屈が違うらしい。


インスタンスメソッド

名前から想像できるけど、インスタンスが持つメソッド。
アクセスする時は、そのオブジェクトを介して行う。

function Rect(w,h) {
 this.width = w;
 this.height = h;
}

var rec1 = new Rect(5,10);
rec1.area = function(){ 〜 }

var a = hoge1.area():
alert(a);

アクセスされたメソッドは、thisキーワードでもって対象のインスタンスを参照する(どのインスタンスから呼ばれたのか)。
このthisはJSでは必須。JAVAなんかだと省略できるらしい。
まあでも、前半の内容でメソッドはインスタンスではなくクラス側に書こう、という内容があったけど、どうなんだろう。使い分ける理由とかあるのだろうか。

他のクラスベースのオブジェクト指向言語では、インスタンスメソッドはそもそも共有できる、という仕組みらしい?

クラスプロパティ

クラスに存在するプロパティ。インスタンスがいくつあっても、クラスプロパティはひとつだけ。
JSでクラスと言うとコンストラクタ関数なので、つまりコンストラクタ関数にプロパティを設定すればよい。

function Rect(w,h) {
 this.width = w;
 this.height = h;
}

Rect.UNIT = new Rect(5,100);

コンストラクタ関数はその名の通り関数だけど、JSの関数はオブジェクトなのでプロパティを設定する事ができる。
インスタンスプロパティにアクセスする時にはインスタンスのオブジェクトを介したけど、クラスプロパティにアクセスする時はクラスを介してアクセスする。

クラスメソッド

クラスに設定され、クラスを介して呼び出されるメソッドの事。クラスを介するという事は、コンストラクタ関数を介して呼び出すという事。
もしthisを使うと、そのthisはインスタンスではなくクラスメソッド自身を指す(オブジェクト生成の時はインスタンスを指す)。
クラスメソッドとクラスプロパティはグローバルな存在なので、上書きされる事がないというメリットが存在する。

function Rect(w,h) {
 this.width = w;
 this.height = h;
}

Rect.CONTAINER = function hoge() { 〜 }

ダックタイピング

「アヒルのように歩いて、アヒルのように鳴くなら、それはアヒルである」という、アメリカの古い格言に基づいた考え方。
JSをこれにあてはめると、「fooというオブジェクトがhogeというクラスのメソッドを実装していれば、fooはhogeクラスのインスタンスである」となる。
JSは弱い型付けの言語なので、例えhogeコンストラクタ関数から生成されたインスタンスでなくても、同じ結果を持つ物ならhogeインスタンスとして扱う事ができる。

これの深い部分は今の自分にはマニアックすぎると感じたので、省略。