簡易なクラス生成関数。
試してみたかった事は本格的なクラスの再現では無いので、
継承機能なんて無い。
だったら関数定義でいいじゃん。
って回りくどいのは、インスタンスからクラスを参照した時の挙動を変えたかったから。
SnipplrClass (instanceof Class)
Posted by inamorix on January 9th, 2008
- function Class (ns) {
- this.toString = function () { return ns; };
- }
- Class.def = function (ns, ctx) {
- var c = window;
- var ns = ns.split('.');
- for (var i = 0, ix = ns.length - 1; i < ix; i++)
- c = c[ns[i]] instanceof Object ? c[ns[i]] : c[ns[i]] = {};
- if (!(ctx.init instanceof Function)) ctx.init = function () {};
- c = c[ns[i]] = function () { this.constructor.apply(this, arguments); };
- c.prototype = new Class(ns.join('.'));
- c.prototype.constructor = ctx.init;
- for (var key in ctx) if (ctx.hasOwnProperty(key)) {
- if (key != 'init') c.prototype[key] = ctx[key];
- }
- return c;
- };
Class.def('com.example.Rect', {
x: 0, y: 0,
init: function (x, y) {
this.x = x;
this.y = y;
},
getArea: function () {
return this.x * this.y;
},
reset: function (x, y) {
this.constructor(x, y);
}
});
r1 = new com.example.Rect(20, 30);
r2 = new com.example.Rect(100, 50);
r1.getArea(); // 600
r2.getArea(); // 5000
Class.defでクラスを定義。
第1引数に名前空間を指定。
第2引数にプロパティやメソッドのオブジェクトを指定。
initはコンストラクタ的に扱われる。
一応、定義されたクラスが戻り値。
ここまでは特に変わった事は無い。
r1 == 'com.example.Rect'; // true r2 == 'com.example.Rect'; // true r1 instanceof Class; // true r2 instanceof Class; // true r1 instanceof com.example.Rect; // true r2 instanceof com.example.Rect; // true
文字列として扱うと、名前空間で指定した文字列が返る。
instanceofでクラスを参照するとClassとして認識される。
Class.defを通して定義されたクラスは、
全てClassのインスタンスとして認識される。
定義したクラス(この場合com.example.Rect)のインスタンスとしても認識される。
厳密に型チェックしたい時は文字列で柔軟に扱えて、
大雑把にチェックする時は共通している方がシンプルなので、
文脈的に綺麗なinstanceofを多用しやすいかな。
試してみたかったのはこれ。
r2.reset(40, 20); r1.getArea(); // 600 r2.getArea(); // 800
メソッドresetはthis.constructorをコールしていて、
コンストラクタはinitの内容を処理するけど、
実際にthis.initは存在しない。