Этот код всегда работает, даже в разных браузерах:
function fooCheck() {
alert(internalFoo()); // We are using internalFoo() here...
return internalFoo(); // And here, even though it has not been defined...
function internalFoo() { return true; } //...until here!
}
fooCheck();
Я не мог найти единственную ссылку на то, почему это должно работать, все же. Я впервые увидел это в записке Джона Резига, но это было только упомянуто. Там нет никакого объяснения там или где-либо в этом отношении.
Может ли кто-нибудь, пожалуйста, просветить меня?
javascript
function
Эду Фелипе
источник
источник
Ответы:
function
Декларация магии и вызывает его идентификатор , чтобы быть связанным , прежде чем что - либо в его код-блок * выполняется.Это отличается от присваивания с
function
выражением, которое оценивается в обычном порядке сверху вниз.Если вы изменили пример, чтобы сказать:
это перестало бы работать.
Объявление функции синтаксически совершенно отдельно от выражения функции, даже если они выглядят почти одинаково и в некоторых случаях могут быть неоднозначными.
Это задокументировано в стандарте ECMAScript , раздел 10.1.3 . К сожалению, ECMA-262 не очень читаемый документ даже по стандартам!
*: содержащая функция, блок, модуль или скрипт.
источник
Это называется HOISTING - вызов (вызов) функции до того, как она была определена.
Два разных типа функций, о которых я хочу написать:
Функции выражения и функции объявления
Функции выражения:
Выражения функций могут храниться в переменной, поэтому им не нужны имена функций. Они также будут названы как анонимная функция (функция без имени).
Для вызова (вызова) этих функций им всегда нужно имя переменной . Функция такого типа не будет работать, если она вызывается до того, как была определена, что означает, что здесь не происходит подъем. Мы всегда должны сначала определять функцию выражения, а затем вызывать ее.
Вот как вы можете написать это в ECMAScript 6:
Функции декларации:
Функции, объявленные со следующим синтаксисом, не выполняются немедленно. Они «сохраняются для последующего использования» и будут выполнены позже, когда они будут вызваны (вызваны). Этот тип функции работает, если вы называете ее ДО или ПОСЛЕ того, где определено. Если вы вызываете функцию объявления до того, как она была определена, Hoisting работает правильно.
Подъемный пример:
источник
let fun = theFunction; fun(); function theFunction() {}
также будет работать (Node и браузеры)Браузер читает ваш HTML от начала до конца и может выполнять его, когда он читается и разбирается на исполняемые фрагменты (объявления переменных, определения функций и т. Д.). Но в любой момент может использовать только то, что было определено в сценарии до этого момента.
Это отличается от других контекстов программирования, которые обрабатывают (компилируют) весь ваш исходный код, возможно, связывают его вместе с любыми библиотеками, которые вам нужны для разрешения ссылок, и создают исполняемый модуль, с которого начинается выполнение.
Ваш код может ссылаться на именованные объекты (переменные, другие функции и т. Д.), Которые определены далее, но вы не можете выполнить ссылочный код, пока не будут доступны все фрагменты.
Когда вы познакомитесь с JavaScript, вы почувствуете, что вам нужно писать вещи в правильной последовательности.
Редакция: Чтобы подтвердить принятый ответ (см. Выше), используйте Firebug для перехода через раздел сценариев на веб-странице. Вы увидите, что он переходит от функции к функции, посещая только первую строку, прежде чем он фактически выполнит какой-либо код.
источник
В некоторых языках требуется, чтобы идентификаторы были определены перед использованием. Причина этого заключается в том, что компилятор использует один проход для исходного кода.
Но если есть несколько проходов (или некоторые проверки отложены), вы можете прекрасно жить без этого требования. В этом случае код, вероятно, сначала читается (и интерпретируется), а затем устанавливаются ссылки.
источник
Я только немного использовал JavaScript. Я не уверен, поможет ли это, но это выглядит очень похоже на то, о чем вы говорите, и может дать некоторое представление:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
источник
Тело функции «internalFoo» должно идти куда-то во время синтаксического анализа, поэтому, когда код читается (или синтаксический анализ) интерпретатором JS, создается структура данных для функции и присваивается имя.
Только позже, затем код запускается, JavaScript фактически пытается выяснить, существует ли «internalFoo» и что это такое, можно ли его вызывать и т. Д.
источник
По той же причине следующее всегда будет помещать
foo
в глобальное пространство имен:источник
if
Блок не создает сферу, в то время какfunction()
блок всегда создает один. Реальная причина заключалась в том, что определение глобальных имен javascript происходит на этапе компиляции, поэтому даже если код не запускается, имя определяется. (Извините, что так долго комментировал)