JavaScriptにおけるnew

new Objectをつくる構文

function Person(name) {
   this.name = name;
}

var p1 = new Person('morita_non');

これだけ見るとJavaとあんまり変わらないように見えますが、

実際こんな感じのようだ。(正確ではない)(prototypeのことは知らん。)

function Person(name) {
  this.name = name;
}

var p1 = function(name) {  // nameを引数とする無名関数をこの場で定義
   var this = {};   // 変数thisを空オブジェクトとして作成
   
   Person(name);    // Personを実行

   return this;     // thisを返却。
}('morita');  //今作った無名関数をその場で実行。
  • Personと大文字で書いてありますが、大文字で書くのは、JavaとかC++のコンストラクタっぽく見せるための単なる慣習です。
  • new 演算子は、関数を引数にとり、thisというローカル変数をでっちあげてるだけです。%%(断言) (要出典)。
  • newをつかわなくても コンストラクタPersonは単なる関0数なので、もちろん呼ぶことが出来ます。
<script type="text/javascript">
function Person(name) {
    this.name = name;
}

function test() {
    var p1 = new Person("morita");
    var p2 = Person("hige");  // Oh! newを書き忘れちゃったZe HaHaHa

    alert(p1.name);
    alert(this.name); 
    alert(this);
    alert(p2);
}
</script>
<body onload="test()"> 
  • alert(p2)や、alert(this.name); で何が表示されるでしょうか?
  • そもそも、このthis何?


newが実行時にthisをコンストラクタ(っぽい関数)の外側にでっちあげてるだけなので、
newを使わずに、Person関数を呼ぶと、test()の外側にthisがあるであろうとみなします。
しかし、thisは外側にも、もちろん定義されてません。

thisは文脈依存の現在の環境を指す組み込み変数なので、でっちあげられるわけではないようす。
その関数がトップレベルに属していれば、トップレベルにプロパティを追加してしまいます。

でもオブジェクトとしてPerson内部で、nameが代入されてるので、(上記の場合はグローバルの)オブジェクトthisが即席で作られ、であるthisにnameメンバが追加されます。
また、Person関数自体にはreturn文がないので、単体のPerson呼び出しでは何も返って来ません。
よって、p2はPersonの戻り値、つまり undefined です。

そして、上記は文法的に正しいので、JavaScriptは一切エラーを出力しません。
本当に、JavaScriptってアレですなあ・・・
JavaScript Good Partsに書いてあったように、newはいらない子でいいと思います。

読んでいないが一応。参考:
http://www2u.biglobe.ne.jp/~oz-07ams/prog/ecma262r3/