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/