Контекст функции («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 - контекст указан явно
Сновый оператор (как конструктор) - контекст является вновь созданным объектом
Не стесняйтесь обновлять вышеупомянутое по мере необходимости, в интересах людей с подобными вопросами. Спасибо!