エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

What is this?

一応JavaScriptで動くコードを書けたというのに、thisがいまひとつ理解できていなかったので、いろいろためしてみた。
使った環境は。Mac OS 10.5 + Safari 4です。


一番外側のスコープから見えるthisはなにか?

document.writeln(this);

結果。Windowだった。

[object DOMWindow]


一番外側のスコープの関数の中から見えるthisはなにか?

function foo()
{
    document.writeln("foo:" + this);
}

foo();

結果。Windowだった。

foo:[object DOMWindow]


オブジェクトを生成するとき、コンストラクタの中か見えるthisはなにか?

function Foo()
{
    document.writeln("Foo:" + this);
}

var foo = new Foo();

結果。生成されるオブジェクトだった。

Foo:[object Object]

本当は、きちんと判断するにはObjectの中身を確認しないといけないんですが、そこはここでは省略します。


メソッドの中から見えるthisはなにか?

function Foo()
{
    document.writeln("Foo:" + this);

    this.hoge = function ()
    {
        document.writeln("Foo.hoge:" + this);
    };
}

var foo = new Foo();
foo.hoge();

結果。メソッドが属するオブジェクトだった。

Foo:[object Object] Foo.hoge:[object Object]


コンストラクタ内で定義されるメソッドでない関数から見えるthisはなにか?

function Foo()
{
    document.writeln("Foo:" + this);

    var fuga = function ()
    {
        document.writeln("Foo.fuga:" + this);
    };

    this.hoge = function ()
    {
        document.writeln("Foo.hoge:" + this);
        fuga();
    };
}

var foo = new Foo();
foo.hoge();

結果。メソッドでない関数から見えたのはWindowだった。

Foo:[object Object] Foo.hoge:[object Object] Foo.fuga:[object DOMWindow]

いままでに学んできたことの延長で考えると、これは思いっきり間違えそうだ。要注意。


別のオブジェクトのメソッドから呼ばれる、一番外側のスコープの関数から見えるthisはなにか?

function Foo()
{
    document.writeln("Foo:" + this);
}

function Bar()
{
    var foo = new Foo();

    this.hoge = function ()
    {
        document.writeln("Bar.hoge:" + this);
        Foo();
    };
}

var bar = new Bar();
bar.hoge();

結果。Windowだった。

Foo:[object Object] Bar.hoge:[object Object] Foo:[object DOMWindow]


別のオブジェクトのメソッドから呼ばれるコンストラクタの中で定義されている関数の中か見えるthisはなにか?

function Foo()
{
    document.writeln("Foo:" + this);

    var fuga = function ()
    {
        document.writeln("Foo.fuga:" + this);
    };

    this.hoge = function ()
    {
        document.writeln("Foo.hoge:" + this);
        fuga();
    };
}

function Bar()
{
    var foo = new Foo();

    this.hoge = function ()
    {
        document.writeln("Bar.hoge:" + this);
        foo.hoge();
    };
}

var bar = new Bar();
bar.hoge();

結果。Windowだった。

Foo:[object Object] Bar.hoge:[object Object] Foo.hoge:[object Object] Foo.fuga:[object DOMWindow]

表に見せない処理だからとコンストラクタの中で関数を定義することがある場合は注意しないといけない。