2006 年 7 月 25 日 18 時 33 分

メソッドと関数


このアーカイブは同期化されません。 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 で同様のことを実現するにはどうすればよいか。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.