JavaScript - コンストラクタ関数

 

JavaScript では、関数を new 演算子とともに使用すると、 new 演算子が生成したオブジェクトを受け取って初期化することが出来ます。

関数は、初期化に必要なオブジェクトを this で受け取るので、 このオブジェクトに対して好きなようにプロパティ(変数)とメソッドを構築できます。 このように、オブジェクトの初期化(構築)を行う関数を、特にコンストラクタ関数と呼びます。

本稿では、コンストラクタ関数に関連する話題を、サンプルで確認しながら一気に流します。

最初に作成するサンプルは、次の要素を網羅しています。

    (1) クラス変数
    (2) インスタンス変数(private)
    (3) インスタンス変数(public)
    (a) クラスメソッド
    (b) インスタンスメソッド(private)
    (c) インスタンスメソッド(public)、非共用
    (d) インスタンスメソッド(public)、共用

(c) と (d) の違いが分りにくいので説明しておきます。 非共用の場合は、インスタンスの数だけメソッドのコピーが作成されるのでメモリ効率の悪い実装です。 共用の場合は、インスタンスの数がいくつであっても、 1つのメソッドをインスタンスで共用するのでメモリ効率の良い実装です。

// コンストラクタ関数 Foo
function Foo(val1, val2)
{
    var value   = val1;                 // (2) インスタンス変数(private)
    this.value  = val2;                 // (3) インスタンス変数(public)

    var getValue = function()           // (b) インスタンスメソッド(private)
    {
        return value;                   //     (2)を返す
    }

    this.getValue2 = function()         // (c) インスタンスメソッド(public)、非共用
    {
        return getValue();              //     (b)を呼び出す
    }
}

Foo.value = 130;                        // (1) クラス変数

Foo.getValue = function()               // (a) クラスメソッド
{
    return Foo.value;                   //     (1)を返す
}

Foo.prototype.getValue = function()     // (d) インスタンスメソッド(public)、共用
{
    return this.value;                  //     (3)を返す
}

Foo のインスタンスにアクセスしてみます。

foo = new Foo(110, 120);

// (1)の値を取得した後、(a)を呼び出す
console.log(Foo.value);                 //=> 130
console.log(Foo.getValue());            //=> 130

// (2)の値を取得するために(c)を呼び出す
console.log(foo.getValue2());           //=> 110

// (3)の値を取得した後、(d)を呼び出す
console.log(foo.value);                 //=> 120
console.log(foo.getValue());            //=> 120

次のサンプルでは、Foo を継承して Qux を作成しています。 Qux では、getValue() メソッドの機能を少しだけ変更しています。

 update 
// コンストラクタ関数 Qux(Foo を継承)
function Qux(val1, val2)
{
    Foo.apply(this, [val1, val2]);      // スーパークラスのコンストラクタを呼び出す
}

Qux.prototype = new Foo;                // Qux は Foo を継承する

Qux.prototype.getValue = function()     // (d)をオーバライドする
{
    // オーバライドされる前の(d)を呼び出した後、戻り値に +1 して返す
    return Foo.prototype.getValue.apply(this, []) + 1;
}

Qux のインスタンスにアクセスしてみます。

qux = new Qux(210, 220);
console.log(qux.getValue2());           //=> 210
console.log(qux.getValue());            //=> 221

改版履歴

日付 内容
2007-02-05 スーパークラスのコンストラクタ呼び出しを綺麗に修正した。
[修正前] this.base = Foo; this.base(val1, val2);
[修正後] Foo.apply(this, [val1, val2]);
2006-10-01 初版