Functionにまつわる変態的検証。

JavaScriptの不思議な言語構造、Function。
どうなるか気になる挙動があったので確認してみた。

Functionをnewするときとcallするときでthisってどうなるの?

まずFunctionが何かっていうと、

var f = function() {};

のようにして作られる「関数型オブジェクト」のこと。
Perlの無名関数のように、そのままcallすることができる。

f();

JavaScript独特の挙動として、このFunctionオブジェクトはクラスのようにも振る舞う。

var o = new f();

とすると、oには「fというクラスのインスタンス」とも言えるオブジェクトが入る。
その他prototypeが云々というのもあるが、今回の件とは関係ないので割愛。

そして本題へ

今回の主旨は、「関数としてもコンストラクタとしても呼べるFunctionを両方の呼び方したらthisの値はどうなるのか」を検証すること。
まずは以下のコード。

var f = function() {
  alert((this === window));
};

f();     // true
new f(); // false

windowのコンテキストで単に呼ぶとthisがwindowになる。
これは普通の挙動として知ってはいた。

本命は以下。

var f = function() {
  alert((this === window));
};

var Foo = new function() {};
Foo.prototype.normal = function() { f(); };
Foo.prototype.create = function() { new f(); };

var foo = new Foo();

foo.normal(); // true
foo.create(); // false

他クラスのインスタンスのコンテキストで呼んでみたらwindowじゃなくてインスタンスがthisになるんじゃないかと思ったけど、
そうでもないらしい。
どこから呼ぼうとapplyなどでコンテキストを明示しない限りwindowをthisとして実行されるようだ。


つまり、if (this === window)でコンストラクタとして呼ばれたかどうかが分かるわけで・・・フフフ