Javascript で最上位関数を呼び出す場合、関数内のthisキーワードはデフォルト オブジェクト (ブラウザの場合はウィンドウ) を参照します。私の理解では、関数をメソッドとして呼び出す特殊なケースであると理解しています。これは、デフォルトではウィンドウで呼び出されるためです (John Resig の著書、Secrets of the JavaScript Ninja、49 ページで説明されているように)。実際、次のコードの両方の呼び出しは同一です。
function func() {
return this;
}
// invoke as a top-level function
console.log(func() === window); // true
// invoke as a method of window
console.log(window.func() === window); // true
これまでのところとても良い...今ここに私が理解していない部分があります:
関数が別の関数にネストされ、呼び出すオブジェクトを指定せずに呼び出された場合、関数内のthisキーワードも window を参照します。ただし、ウィンドウで内部関数を呼び出すことはできません (以下のコードを参照)。
function outerFunc() {
function innerFunc() {
return this;
}
// invoke without window.* - OK
console.log(innerFunc() === window); // true
// invoke on window
//window.innerFunc(); - error (window has no such method)
console.log(window.innerFunc) // undefined
}
outerFunc();
ネストされた関数がウィンドウで使用できないことは完全に理にかなっています。結局のところ、ネストされているためです...しかし、関数がウィンドウで呼び出されたかのように、 this キーワードがウィンドウを参照する理由がわかりません。ここで何が欠けていますか?
編集
これは、以下の優れた回答の要約と、私の追跡調査の一部です。
関数を「普通に」呼び出すことは、 windowのメソッドとして呼び出すことと同じであるというのは誤りです。これは、関数がグローバルに定義されている場合にのみ正しいです。
関数のコンテキスト ( thisキーワードの値) は、関数がどこでどのように定義されているかではなく、どのように呼び出されているかに依存します。
コードが厳密モードで実行されていないと仮定すると、関数を「通常」呼び出すと、関数コンテキストがウィンドウに設定されます (ブラウザーで実行している場合、または他の環境で対応するグローバル オブジェクトを実行している場合)。
上記の規則の例外は、bindを使用して関数を作成する場合です。この場合、関数が「通常どおり」呼び出されたとしても、window以外のコンテキストを持つ可能性があります。つまり、この場合、コンテキストは関数の呼び出し方法ではなく、関数の作成方法によって決定されます。bindはapplyを使用して指定された関数を内部的に呼び出す新しい関数を作成するため、厳密に言えばこれは正確ではありません。その新しい関数のコンテキストは、呼び出された方法によって決定されますが、applyを使用して内部的に呼び出す関数のコンテキストを保護します。
「通常」の呼び出しとは、次の簡単な呼び出し方法を指します。
myFunction();
全体像を完成させるために、他の呼び出し方法と対応するコンテキストについて簡単に説明します。
オブジェクト (メソッド) のプロパティとして - コンテキストはオブジェクトです
apply または call を使用 - コンテキストが明示的に指定されている
new演算子 (コンストラクターとして) を使用- コンテキストは新しく作成されたオブジェクトです
同様の質問を持つ人々のために、必要に応じて上記を自由に更新してください。ありがとう!