Сколько программ JavaScript выполняется для одной веб-страницы в браузере?

Программы JavaScript состоят из операторов и объявлений функций. Когда выполняется программа JavaScript, выполняются следующие два шага:

  1. код сканируется на наличие объявлений функций и всех функций. объявление "выполняется" (путем создания объекта функции) и создается именованная ссылка на эту функцию (так что эта функция может быть вызвана из оператора)

  2. операторы выполняются (оцениваются) последовательно (как они появляются в коде)

Из-за этого это работает просто отлично:

<script>
    foo();
    function foo() {
        return;
    }
</script>

Хотя функция "foo" вызывается до ее объявления, она работает, потому что объявление функции вычисляется перед оператором.

Однако это не работает:

<script>
    foo();
</script>
<script>
    function foo() {
        return;
    }
</script>

Будет сгенерировано ReferenceError ("foo не определен"). Это приводит к выводу, что каждый элемент SCRIPT внутри HTML-кода веб-страницы представляет отдельную программу JavaScript, и каждый раз, когда анализатор HTML встречает элемент SCRIPT, он выполняет программу внутри этого элемента (а затем, как только программа выполняется, парсер переходит к HTML-коду, который следует за элементом SCRIPT).

Опять же, это работает:

<script>
    function foo() {
        return;
    }
</script>
<script>
    foo();
</script>

Насколько я понимаю, глобальный объект (который служит объектом переменной в глобальном контексте выполнения) существует (и остается) всегда, поэтому первая программа JavaScript создаст объект функции и создаст для него ссылку, а затем вторая программа JavaScript будет использовать эту ссылку для вызова функции. Следовательно, все программы JavaScript (в пределах одной веб-страницы) "используют" один и тот же глобальный объект, и все изменения, сделанные в глобальном объекте одной программой JavaScript, могут наблюдаться всеми программами JavaScript, которые запускаются впоследствии.

Теперь обратите внимание на это...

<script>
    // assuming that foo is not defined
    foo();
    alert(1);
</script>

В вышеприведенном случае вызов оповещения не будет выполнен, поскольку оператор "foo()" выбрасывает объект ReferenceError (который нарушает всю программу JavaScript) и, следовательно, все последующие операторы не выполняются.

Однако в этом случае...

<script>
    // assuming that foo is not defined
    foo();
</script>
<script>
    alert(1);
</script>

Теперь предупреждающий вызов выполняется. Первая JavaScript-программа генерирует ReferenceError (и, как следствие, прерывается), но вторая JavaScript-программа работает нормально. Конечно, браузер сообщит об ошибке (хотя он и выполнял последующие программы JavaScript после возникновения ошибки).

Теперь мои выводы:

  • каждый элемент SCRIPT в HTML-коде веб-страницы представляет собой отдельную программу JavaScript. Эти программы выполняются сразу же, как только синтаксический анализатор HTML сталкивается с ними.
  • все программы JavaScript на одной веб-странице "используют" один и тот же объект Global. Этот Глобальный объект существует постоянно (с момента загрузки веб-страницы до ее уничтожения). Программы JavaScript могут манипулировать объектом Global, и все изменения, внесенные в объект Global одной программой JavaScript, можно наблюдать во всех последующих программах JavaScript.
  • если одна из программ JavaScript выходит из строя (из-за ошибки), это не мешает выполнению последующих программ JavaScript.

Пожалуйста, проверьте этот пост и скажите, если я что-то не так понял.

Кроме того, я не нашел ресурсов, объясняющих поведение, упомянутое в этом посте, и я предполагаю, что производители браузеров, должно быть, где-то публиковали такие ресурсы, поэтому, если вы знаете о них, пожалуйста, предоставьте ссылки на них.

Ответ 1

Дмитрий Сошников ответил на ваш вопрос. Каждый элемент <script> выполняется как программа, как определено спецификацией ECMAScript. Существует один глобальный объект, который использует каждая Программа на одной странице. И это действительно так.

Ответ 2

Поднятие функций - процесс, который оценивает операторы function перед остальной частью функции - является частью стандарта IIRC ECMAScript (я не могу найти ссылку прямо сейчас, но я вспоминаю, что обсуждают EMCAScript, который упоминает об этом), Оценка тегов script является частью стандарта HTML. Он не указывает, что они являются "отдельными программами" во многих словах, но он говорит, что элементы script оцениваются в том порядке, в котором они отображаются в документе. Поэтому функции в тегах script не выполняются: script еще не оценен. Это также объясняет, почему одна остановка script не прерывает последующие сценарии: когда текущий script перестает оценивать, начинается следующий.

Ответ 3

Это отдельные программы, но они изменяют общий глобальный объект.

Ответ 4

Другой способ подумать об этом - это псевдо-локальная или глобальная область. Каждое объявление SCRIPT имеет локальную область действия для текущих методов/функций, а также доступ к текущей (ранее объявленной) глобальной области. Всякий раз, когда метод/функция определяется в блоке SCRIPT, он затем добавляется в глобальную область видимости и становится доступной блоками SCRIPT после него.

Кроме того, здесь еще одна ссылка из W3C в объявлении/обработке/модификации SCRIPT:

Динамическая модификация документа могут быть смоделированы следующим образом:

  • Все элементы SCRIPT оцениваются в порядке загрузки документа.
  • Все SCRIPT конструкции в пределах данного элемента SCRIPT, которые генерируют SGML CDATA оцениваются. Их комбинированный сгенерированный текст документ вместо SCRIPTэлемент.
  • Сгенерированная CDATA переоценивается.

Этот является еще одним хорошим ресурсом в script/оценке/объявлении функции.