log.metatype

Archive for January 2008

Class (instanceof Class)

簡易なクラス生成関数。
試してみたかった事は本格的なクラスの再現では無いので、
継承機能なんて無い。
だったら関数定義でいいじゃん。
って回りくどいのは、インスタンスからクラスを参照した時の挙動を変えたかったから。

SnipplrClass (instanceof Class)

Posted by inamorix on January 9th, 2008

  1. function Class (ns) {
  2.         this.toString = function () { return ns; };
  3. }
  4. Class.def = function (ns, ctx) {
  5.         var c  = window;
  6.         var ns = ns.split('.');
  7.         for (var i = 0, ix = ns.length - 1; i < ix; i++)
  8.                 c = c[ns[i]] instanceof Object ? c[ns[i]] : c[ns[i]] = {};
  9.        
  10.         if (!(ctx.init instanceof Function)) ctx.init = function () {};
  11.         c = c[ns[i]] = function () { this.constructor.apply(this, arguments); };
  12.         c.prototype             = new Class(ns.join('.'));
  13.         c.prototype.constructor = ctx.init;
  14.         for (var key in ctx) if (ctx.hasOwnProperty(key)) {
  15.                 if (key != 'init') c.prototype[key] = ctx[key];
  16.         }
  17.        
  18.         return c;
  19. };


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は存在しない。

alert with Force Quit

無限ループや、極端に周期が短いset(Timeout or Interval)や、
予想よりも列挙が大量な場所で、
alert()を使ってしまった時に強制終了できるやつ。

要は、間違えちゃった時にキャンセルできるalert()

どこかで既に出ていると思うけど、
まあ、いいや。

Snipplralert with Force Quit

Posted by inamorix on January 9th, 2008

  1. window.alert = function (msg) {
  2.         if (!confirm(msg)) throw new Error('Force Quit');
  3. };