JavaScriptでクラスもどきを定義するとき、次のような書き方があります。
// パッケージ var shape = {}; // コンストラクタ shape.Point = function (x, y) { this.x = x; this.y = y; }; // クラス変数やメソッド shape.Point.prototype = { moveTo : function (toX, toY) { this.x = toX; this.y = toY; }, // 以下略 };
僕はこのスタイルを使っていませんでした(代わりに大域変数を1つゴミにしている例は「JavaScriptで言語処理系の勉強をしましょう:字句解析編」)。特にこれといった理由はなくて、「インデントどうしたらいいかわかんない」とか、その程度の事情です。
しかし、プロパティのgetter/setterを使うときは、上の書き方しかないような気がします。(ひょっとすると、別な書き方でもgetter/setterが使えるのかもしれません; ご存知の方は教えてください。)
例題として、Pointクラスにcolorを追加したものを使いましょう。colorは、RGBを表す3つの数値からなる配列とします。
// パッケージ var shape = {}; // コンストラクタ shape.Point = function (x, y) { this.x = x; this.y = y; }; // クラス変数やメソッド shape.Point.prototype = { color : [0, 0, 0], // デフォルト値 moveTo : function (toX, toY) { this.x = toX; this.y = toY; }, // 以下略 };
これだけでも、Pointのインスタンスはcolorの初期値を持ちます。個別にcolorを設定したいなら、p.color = [255, 0, 0] のようにしてできます。
フィールドアクセスや代入を生で使うよりは洒落た方法を使いたいなら、IEを除くたいていのブラウザでgetter/setterが使えます。
// クラス変数やメソッド shape.Point.prototype = { _color : [0, 0, 0], // デフォルト値 get color() { return this._color; }, set color(c) { this._color = c; }, moveTo : function (toX, toY) { this.x = toX; this.y = toY; }, // 以下略 };
こうすると、p.color (参照)とか p.color = [255, 0, 0] (代入)とかのタイミングで関数が呼び出されます。もっとも、これだけでは以前と変わりません。色名(文字列)を、RGB数値配列に変換する処理を入れてみます。
// クラス変数やメソッド shape.Point.prototype = { _color : [0, 0, 0], // デフォルト値 get color() { return this._color; }, set color(c) { if (typeof(c) === 'string') { var col = this.colorValue[c]; if (col) { this._color = col; } } else if (c instanceof Array && c.length === 3) { // 配列の各項目のチェックは省略 this._color = c; } // その他は何もしない }, colorValue : { "black" : [0, 0, 0], "white" : [255, 255, 255], "red" : [255, 0, 0], "green" : [0, 255, 0], "blue" : [0, 0, 255] }, moveTo : function (toX, toY) { this.x = toX; this.y = toY; }, // 以下略 };
これで、p.color = "red"; のような書き方もできるようになります。便利ですね。