newを実装する
Function.prototype.neo =function(){ var obj={}; obj.__proto__ = this.prototype; var ret = this.apply(obj,arguments); if( ret && typeof(ret)=='object' ){ delete obj; obj = ret; } return obj; }
ふむ… obj={} は obj= new Object なので「実装する」と偉そうに言ったわりにアレだが、別に実装が目的ではなくてJavascriptのnew(とthis)の動きを理解するためのサンプルだからこれでいいのだ。
プロトタイプチェーン __proto__ をいじれる系(firefoxとか)なら、だいたいうまくいくはず。
// クラス定義のようなもの function Klass(x){ this.x = x; } Klass.prototype.add1=function(){ return this.x+1; } // 使ってみる obj = Klass.neo(1); // <= obj = new Klass(1) obj.x // => 1 obj.add1() // => 2 typeof obj // => 'object' obj instanceof Klass // => true obj.constructor == Klass // => true
constructor プロパティーや instanceof までちゃんと動く。
解説しよう。
Function.prototype.neo =function(){ // 新たなインスタンス obj にメモリを割り当てる var obj={}; // プロトタイプチェーンをつなげる obj.__proto__ = this.prototype; // 変数 this に、上2行で初期化した obj をセットして // コンストラクタ関数を呼ぶ var ret = this.apply( obj, arguments ); // 次の if 文がやっているのは、 // コンストラクタ関数がthis以外を返すこともできる // というjavascriptの動作のエミュレート。 if( ret && typeof(ret)=='object' ){ // null以外のobjectが返ってきた場合は、 // new演算子が作成したインスタンスを捨てて delete obj; // 返ってきた値を作成したことにする var obj = ret; } return obj; }
*1:newとして設定することもできるが記述が煩雑になるだけ