メソッドとして関数を呼んだ場合の this の値
今日は、うっかり忘れがちな「メソッド内の this が何を示すか」を復習するついでに、脳内ダンプしてみます。
C++ の this には、
- 「this(ポインタ)は メソッドの親オブジェクトを示す」
- 「メソッド内では、 this->hoge() と hoge() は同じ意味になる。thisは省略できる(例外あり)(テンプレート内の名前解決とか)」
- 「関数の中では this は未定義」
と、明確なルールがありますが、JavaScript の this は呼び出し方により中身が変化する BuzzWord です。
obj1.obj2.fn() の fn の中で this は何になるか
window.x = "global"; window.fn = function() { alert(this === window); alert(this.x); }; window.lv1 = { x: "lv1", fn: function() { alert(this === lv1); alert(this.x); }, lv2: { x: "lv2", fn: function () { alert(this === lv1.lv2); alert(this.x); } } };
実行するとこうなる
window.fn(); // true, "global" window.lv1.fn(); // true, "lv1" window.lv1.lv2.fn(); // true, "lv2
JavaScript的には
- ドット は 「オブジェクトの要素にアクセスする演算子」
- () は「要素を関数として呼び出す演算子」
- オブジェクトに紐づいている関数はメソッドと呼ばれる
- 関数とメソッドは扱いが異なる
- 「メソッドを呼び出すときに使用したオブジェクトが、メソッドの本体の中で this キーワードの値になる」(サイ本 8.4 メソッドとしての関数)
- メソッド呼び出しは、メソッドが所属するオブジェクト(thisが表すもの)を処理するための構文
- メソッド呼び出しでは、this が暗黙のうちに設定され、渡される。
- メソッド呼び出しは、メソッドが所属するオブジェクト(thisが表すもの)を処理するための構文
長いですね。
つまり
obj1.obj2.fn() の中の this は obj1.obj2 です。
obj1.obj2.fn() は、「obj1 の要素の obj2 の fn という要素を、obj1.obj2 を this としたメソッドとして実行する」 という意味になります。
これらを踏まえると
↓は上記の例と同じ結果になります(無駄に長くて遅いけど)
window.fn.call(window); // == window.fn() window.lv1.fn.call(window.lv1); // == window.lv1.fn(); window.lv1.lv2.fn.call(window.lv1.lv2); // == window.lv1.lv2.fn();
Function.call や Function.apply に undefined や null を渡すと、トップレベルオブジェクト(ブラウザ上なら window) が渡されるため、
↓も同じ結果になります。
window.fn.call(); // == window.fn()