理解するための良い方法は次のthis
とおりです(しゃれが意図されています):
関数内の の値はthis
、関数の呼び出し方法によって決まります。1 つの例外を除いて、関数が定義されている場所、内部にネストされている他の関数、関数が一部として定義されているオブジェクト、関数の種類などとは関係ありません。
foo.bar()
またはfoo[bar]()
のようなメソッド呼び出しを使用して関数を呼び出すと、関数this
内にfoo
オブジェクトがあります。
のような通常の関数呼び出しで関数を呼び出す場合foo()
、this
関数内はwindow
オブジェクトであり、関数が厳密モードを使用する場合は ですundefined
。
これは 1 つの例外です。関数自体またはその周囲のコードが単純な関数呼び出しに対して"use strict";
変更されている場合です。this
違いを生むべきではない良いコードについては、とにかくオブジェクトであることに依存するコードを書くべきではありませthis
んwindow
。
それ以外の場合、気this
にするのは、メソッド呼び出しでオブジェクトが参照するものです。そしてそれは、関数の定義方法ではなく、関数の呼び出し方法によって常に決定されます。
最初の例を見てみましょう。
を呼び出すときは、オブジェクトのメソッドとしてa.b()
呼び出しています。したがって、関数内では、 と同じです。b
a
b
this
a
たまたま、それを知っても何のb
役にも立ちません。関数は に対して何もしないからthis
です。c()
通常の関数として呼び出すだけです。c
そのため、内部this
はwindow
オブジェクトです。またはundefined
、厳密モードの場合はそうなります。
このc
関数は単にそのthis
値またはを返しますwindow
。そして、それは からの戻り値でもありますb
。これが、結果として表示される理由です。すべては、コードが関数と関数をwindow
呼び出す方法に由来します。b
c
次に、2 番目の例について説明します。これはひどく難読化されたコードですよね。誰がこのコードを書き、誰でも一目で理解できると期待するでしょうか?
それでは、より読みやすい形式に変換しましょう。この行が問題です:
return (function() {return this;})();
括弧で囲まれた関数式を取り出してみましょう:
(function() {return this;})
それを一時変数に割り当てます。
var temp = (function() {return this;});
余分な括弧はもう必要ありません。読みやすくするためにコードをインデントしましょう。
var temp = function() {
return this;
};
そして、その変数をステートメントtemp
で関数として呼び出すことができます。return
return temp();
b
これをコード例の関数に戻すことができます。
var a = {
b: function() {
var temp = function() {
return this;
};
return temp();
}
};
a.b(); //window
おい!そのコードは見覚えがありませんか? temp
実際、変数の名前を除いて、最初の例と同じです。これで、最初のものと同じように機能する理由がわかります。