Kontekst funkcji („to”) w zagnieżdżonych funkcjach

Kiedy wywołujesz funkcję najwyższego poziomu w Javascript,to słowo kluczowe wewnątrz funkcji odnosi się do domyślnego obiektu (okno, jeśli w przeglądarce). Rozumiem, że jest to specjalny przypadek wywołania funkcji jako metody, ponieważ domyślnie jest wywoływany w oknie (jak wyjaśniono w książce Johna Resiga, Secrets of the JavaScript Ninja, strona 49). I rzeczywiście oba wywołania w następującym kodzie są identyczne.

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

Do tej pory tak dobrze ... Teraz jest część, której nie rozumiem:

Gdy funkcja jest zagnieżdżona w innej funkcji i wywoływana bez określania obiektu do wywołania,to słowo kluczowe wewnątrz funkcji odnosi się również do okna. Ale funkcji wewnętrznej nie można wywołać w oknie (patrz kod poniżej).

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();

Ma to sens, że zagnieżdżona funkcja nie jest dostępna w oknie, ponieważ jest po wszystkim zagnieżdżona ... Ale wtedy nie rozumiem, dlaczego słowo kluczowe odnosi się do okna, tak jakby funkcja była wywoływana w oknie. Czego mi tu brakuje?

EDYTOWAĆ

Oto podsumowanie wspaniałych odpowiedzi poniżej i niektóre z moich badań uzupełniających.

Błędem jest twierdzenie, że wywołanie funkcji „normalnie” jest tym samym, co wywołanie jej jako metodyokno. Jest to poprawne tylko wtedy, gdy funkcja jest zdefiniowana globalnie.

Kontekst funkcji (wartośćto słowo kluczowe) nie zależy od tego, gdzie / jak funkcja jest zdefiniowana, ale od tego, jak jest wywoływana.

Zakładając, że kod nie działa w trybie ścisłym, Wywołanie funkcji „normalnie” spowoduje, że kontekst funkcji zostanie ustawiony na okno (przy uruchomieniu w przeglądarce lub odpowiadający obiekt globalny w innych środowiskach).

Wyjątkiem od powyższych zasad jest użyciewiązać stworzyć funkcję. W tym przypadku nawet jeśli funkcja zostanie wywołana „normalnie”, może mieć kontekst inny niżokno. Oznacza to, że w tym przypadku kontekst jest określony przez sposób tworzenia funkcji, a nie przez sposób jej wywoływania. Chociaż ściśle mówiąc, nie jest to dokładne, ponieważwiązać tworzy nową funkcję, która wewnętrznie wywołuje daną funkcję za pomocązastosować. Kontekst tej nowej funkcji będzie nadal określany przez sposób jej wywoływania, ale chroni kontekst funkcji, którą wewnętrznie wywołuje za pomocązastosować.

Przywołując „normalnie”, odwołuję się do następującego prostego sposobu wywołania:

myFunction();

Aby uzupełnić obraz, oto krótki opis innych sposobów wywoływania i odpowiedniego kontekstu:

Jako właściwość obiektu (metody) - kontekstem jest obiekt

Używanie Zastosuj lub Wywołaj - kontekst jest wyraźnie określony

ZNowy operator (jako konstruktor) - kontekst jest nowo utworzonym obiektem

W razie potrzeby zaktualizuj powyższe, z korzyścią dla osób z podobnymi pytaniami. Dzięki!

questionAnswers(5)

yourAnswerToTheQuestion