JavaScriptでは、プロトタイプベースのオブジェクト指向で、クラスベースに慣れているとちょっと感覚が違う。
先日、JavaScriptでnewを忘れるとグローバル変数を上書きしてしまう - ウェブライフハックという記事を書いたのだが、その実験をやってみました。
試したのは、普通の関数宣言と関数リテラルの書き方で、それぞれnewを付ける/newを付け忘れ、の以下4ケースでのコード。
Firebugのコンソールからコード実行して、その結果も表記。
prop = "グローバル";
var o = function() { this.prop = "プロパティ" }
obj = new o();
console.log(prop); // グローバル
prop = "グローバル";
var o = function() { this.prop = "プロパティ" }
obj = o;
console.log(prop); // グローバル
prop = "グローバル";
function User() { this.prop = "プロパティ" }
obj = new User();
console.log(prop); // グローバル
prop = "グローバル";
function User() { this.prop = "プロパティ" }
obj = User();
console.log(prop); // プロパティ
一番下だけ、出力がプロパティとなり、newを付け忘れたため、グローバル変数propが上書きされています。
これは、バグの原因になりそうだなぁ。
さらに、 this.propのthisが何になっているかを確認するために、以下のように書いて、obj がどのクラスに属するかを調べる。(JavaScriptの場合、クラスという言葉は使わないのでしょうけどけど便宜的に。)
obj にtoStringメソッドをapplyで適用してみる。
prop = "グローバル";
var o = function() { this.prop = "プロパティ" }
obj = new o();
console.log(prop);
console.log(Object.prototype.toString.apply( obj ));
prop = "グローバル";
var o = function() { this.prop = "プロパティ" }
obj = o;
console.log(prop);
console.log(Object.prototype.toString.apply( obj ));
prop = "グローバル";
function User() { this.prop = "プロパティ" }
obj = new User();
console.log(prop);
console.log(Object.prototype.toString.apply( obj ));
prop = "グローバル";
function User() { this.prop = "プロパティ" }
obj = User();
console.log(prop);
console.log(Object.prototype.toString.apply( obj ));
実行結果。
グローバル [object Object] グローバル [object Function] グローバル [object Object] プロパティ [object Window]
やはり、最後のグローバル変数を上書きしているのは、Windowクラス(グローバル)となっています。
newすると、Objectクラスとなり、2番目のように関数リテラルはFunctionクラスとなっています。
■この記事のトラックバックURL:
http://www.mapee.jp/mpe334/mt-tb.cgi/486