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 // => trueconstructor プロパティーや 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として設定することもできるが記述が煩雑になるだけ