このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。
今日は MixiSession クラスのメソッドを考えてみる。
必要なメソッドは、とりあえず以下の 2 つにしよう。
・fetch(url, query)
・post(url, form)
fetch や post は、url を取得し、HTML 文字列を返す。
fetch は GET 用、post は POST 用とする。
では、昨日のコードに追加してみる。
========== MixiSession.js ==========
// クラスのコンストラクタ
function MixiSession(mailAddress, password) {
// フィールド定義
// 内部で利用する XMLHttpRequest
this._client = new XMLHttpRequest();
// メソッド定義
this.fetch = MixiSession_fetch;
this.post = MixiSession_post;
}
// GET を発行して結果の HTML を返す
function MixiSession_fetch(url, query) {
// this._client.open(~) などの処理
};
// POST を発行して結果の HTML を返す
function MixiSession_post(url, form) {
// this._client.open(~) などの処理
};
========== end of MixiSession.js ==========
fetch と post の 2 つのメソッドを定義している。
よく見ると、フィールドと同じような代入構文だ。
JavaScript では、フィールドやメソッドの区別はなく
どちらも「プロパティ」として扱われる。
オブジェクトのプロパティが「関数」を値として持つ場合、
そのプロパティは、メソッドとして利用できるのだ。
JavaScript では、関数もオブジェクトであり、
Function 型のインスタンスである。
関数は () をつけることで「呼び出す」ことができるという
特徴を持つ、オブジェクトの 1 種なのである。
なので、関数も変数やプロパティに代入することができる。
関数が、オブジェクトのプロパティから呼び出される場合、
関数内ではそのオブジェクトを this として参照できる。
そのため、プロパティとして格納した関数を、
メソッドのように利用することが可能となっているのだ。
var session = new MixiSession("hoge", "fuga");
session.fetch("http://hogehoge.domain.local/");
この場合、fetch 内では session を this から参照できる。
さて、MixiSession 型のオブジェクトは、
new MixiSession() で量産することができる。
var s1 = new MixiSession("foo", "bar");
var s2 = new MixiSession("hoge", "fuga");
var s3 = new MixiSession("uga", "geho");
MixiSession 関数はコンストラクタとして機能し、
各インスタンスに対して実行される。
つまり、_client、fetch、post といったプロパティは、
「インスタンスごと」に個別のものが割り当てられる。
_client は フィールドの役割を持つプロパティで、
XMLHttpRequest オブジェクトを格納している。
これはインスタンスごとに異なるオブジェクトが必要だ。
なので、_client は特に問題はない。
では、fetch や post はどうか。
メソッドもプロパティには変わりないので、
インスタンス毎にプロパティが割り当てられる。
でも、それらプロパティは全く同じ関数を指している。
そのため、クラスに数多くのメソッドを定義し、
そのインスタンスを大量に作成した場合、
無駄なメモリを消費してしまうことになる。
まあ、同じ型にも関わらず、特定のインスタンスだけを
突然変異的に違う挙動にするような変な使い方はできるが、
そういうことをすると、クラス風に設計したメリットがない。
Java や C# などのクラスベースの言語では、
メソッドを増やしたところで
インスタンスのサイズには影響はない。
それは、メソッドがインスタンスではなく、
型に関連付けられているからだ。
JavaScript で同様のことを実現するにはどうすればよいか。