JavaScript 第5版 - 9章 クラスとコンストラクタとプロトタイプ(2)

JavaScript 第5版、「9章 クラスとコンストラクタとプロトタイプ」の「9.3.1 インスタンスプロパティ」~「9.3.7 プライベートメンバ」(158~165ページ)を読み進めていきます。

9.3 JavaScriptの「クラス」

9.3.5 Circleクラスの例

JavaScriptでクラスを実現するには次のようなコードになります。

// Circleクラスのコンストラクタ
function Circle(radius) {
    this.r = radius;  // インスタンスプロパティ。インスタンスごとに生成される。

    // インスタンスメソッドは次のようにしてもよい。
    // this.area = function() { return Circle.PI * this.r * this.r; };
}

Circle.PI = 3.14149;  // クラスプロパティ。コンストラクタ関数にプロパティを追加。

// インスタンスメソッド。
// プロトタイプチェーンによって、
// インスタンスのメソッドを上書きしない限りは、全てのインスタンスから共通で参照される。
Circle.prototype.area = function() { return Circle.PI * this.r * this.r; };

// クラスメソッド。
Circle.max = function() { if (a.r > b.r) return a; else return b; };

インスタンスメソッドはコンストラクタ関数内で定義することも可能(コメントアウトしている部分)ですが、インスタンスごとに新たにメソッドが生成されるため、その分のメモリを消費します。通常、インスタンスメソッドは、全てのインスタンスで共通であることがほとんどであるため、コンストラクタ関数のプロトタイプオブジェクトに追加しておきます。必要に応じて、インスタンスに同名のメソッドを追加することで、プロトタイプオブジェクトのメソッドはインスタンス固有のメソッドで隠されます。

9.3.7 プライベートメンバ

JavaScriptでプライベートメンバを実現するには、次のようにクロージャを使います。あまり良い例ではないと思いますが、長方形のサイズ(xy)とスケール(scale)を初期値として、zoomメソッドを呼び出すたびにサイズを拡大するクラスです。スケールは最大で3倍までとなっています。

function Rectangle(x, y, scale) {
    // パブリックプロパティ。長方形のサイズ。
    this.x = x;
    this.y = y;

    // プライベートプロパティ(変数)。長方形のスケール。
    // わかりやすいように別の変数に代入しているが、
    // 引数もCallオブジェクトの一部であり、クロージャーによってスコープが保持されるため、
    // scaleをそのまま使っても良い。
    var _scale = scale;

    // 入れ子型の関数内ではthisキーワードのスコープが変わるため、
    // thisの値(Rectangle関数オブジェクトへの参照)を待避。
    var _self = this;  // プライベートプロパティ(変数)。

    // プライベートメソッド(関数)。サイズを拡大。
    function _zoom() {
        _scale = (++ _scale < 3) ? _scale : 3;
    }

    // プライベートメンバにアクセスするパブリックメソッド(アクセサメソッド)。
    // スケールを返す。
    this.getZoom = function() { return _scale; };
    // 拡大された長方形の面積を返す。
    this.getArea = function() { return _self.x * _self.y * _scale; };
    // 長方形を1段階拡大する。
    this.zoom = function(zoom) { _zoom(); };
}

// パブリックメソッド。オリジナルの長方形の面積を返す。
Rectangle.prototype.getOriginalArea = function() { return this.x * this.y; };

var rect1= new Rectangle(2, 4, 1);
var rect2 = new Rectangle(4, 8, 1);
alert(rect1.getOriginalArea());  // '8'
alert(rect2.getOriginalArea());  // '32'
rect1.zoom();
alert(rect1.getArea());  // '16'
rect2.zoom();
alert(rect2.getArea());  // '64'
rect1.zoom();
alert(rect1.getArea());  // '24'
rect1.zoom();
alert(rect1.getArea());  // '24'

プライベートメンバにアクセスするパブリックメソッドは、プロトタイプオブジェクトから継承することはできません。なぜなら、入れ子型の関数をグローバルスコープから参照することによって、その関数と外側の関数のスコープが保持されるという、クロージャの性質を利用してプライベートメンバを実現しているからです。

JavaScriptはプロトタイプベースのオブジェクト指向プログラミング言語なので、JavaScriptのクラスはクラスベースの言語のクラスとは異なります。現在、ActionScriptなどではクラスベースの言語と同じようなクラスが使えますが、JavaScript 2(ECMAScript 4)にて正式にクラスが使えるようになります。Webでも大々的に使えるようになる日が近いかどうかは、IEの対応次第、その他のブラウザのシェアの拡大次第といったところでしょうか。

コメント (0)

この記事へのコメントはまだありません。

コメントフォーム

トラックバック (0)

この記事へのトラックバックはまだありません。

この記事のトラックバックURI
http://dxd8.com/archives/83/trackback/
この記事のURI
http://dxd8.com/archives/83/