Контекст функции («this») во вложенных функциях

Когда вы вызываете функцию верхнего уровня в Javascript,это Ключевое слово внутри функции относится к объекту по умолчанию (окно в браузере). Насколько я понимаю, это особый случай вызова функции как метода, потому что по умолчанию она вызывается в окне (как объяснено в книге Джона Резига «Секреты ниндзя JavaScript», стр. 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

Пока все хорошо ... Теперь вот часть, которую я не понимаю:

Когда функция вложена в другую функцию и вызывается без указания объекта для вызова,это Ключевое слово внутри функции также относится к окну. Но внутренняя функция не может быть вызвана в окне (см. Код ниже).

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 относится к окну, как если бы функция была вызвана в окне. Что мне здесь не хватает?

РЕДАКТИРОВАТЬ

Вот краткое изложение замечательных ответов ниже и некоторые из моих последующих исследований.

Неверно говорить, что вызов функции «обычно» - это то же самое, что вызов ее как методаокно, Это правильно, только если функция определена глобально.

Контекст функции (значениеэто Ключевое слово) зависит не от того, где и как определяется функция, а от того, как она вызывается.

Предполагая, что код не запускается в строгом режиме, при вызове функции «обычно» будет задан контекст функции для окна (при запуске в браузере или соответствующему глобальному объекту в других средах).

Исключением из вышеуказанных правил является использованиепривязывать создать функцию. В этом случае, даже если функция вызывается «нормально», она может иметь контекст, отличный отокно, То есть в этом случае контекст определяется тем, как вы создаете функцию, а не тем, как вы ее вызываете. Хотя, строго говоря, это не точно, потому чтопривязывать создает новую функцию, которая внутренне вызывает данную функцию, используяприменять, Контекст этой новой функции будет по-прежнему определяться тем, как она вызывается, но она экранирует контекст функции, которую она вызывает изнутри, используяприменять.

Вызывая «обычно», я ссылаюсь на следующий простой способ вызова:

myFunction();

Чтобы завершить картину, вот краткий обзор других способов вызова и соответствующего контекста:

Как свойство объекта (метода) - контекст является объектом

Использование apply или call - контекст указан явно

Сновый оператор (как конструктор) - контекст является вновь созданным объектом

Не стесняйтесь обновлять вышеупомянутое по мере необходимости, в интересах людей с подобными вопросами. Спасибо!

Ответы на вопрос(5)

Ваш ответ на вопрос