Почему видимость функции JavaScript зависит от объявления в том же или другом блоке script в HTML

Если я реализую следующий код кода JavaScript в разметке HTML:

    <script type="text/javascript">
        function MyFunc() {
            alert(1);
        }
        var f1 = MyFunc;
    </script>
    <script type="text/javascript">
        function MyFunc() {
            alert(2)
        }
    </script>
    <script type="text/javascript">
        f1();
    </script>

Я получаю сообщение "1". Однако, если я использую следующий код:

<script type="text/javascript">
            function MyFunc() {
                alert(1);
            }
            var f1 = MyFunc;
            function MyFunc() {
                alert(2)
            }
        </script>
        <script type="text/javascript">

        </script>
        <script type="text/javascript">
            f1();
        </script>

Я получаю "2". Зачем? Протестировано в IE10, последнем FF, Chrome.

Ответы

Ответ 1

Каждый элемент script анализируется и выполняется по порядку. В первом случае назначение f1 выполняется до обработки второго объявления.

Во втором случае обе декларации анализируются до того, как выполняется назначение (поскольку объявления обрабатываются до того, как выполняется какой-либо код), поэтому второе объявление заменяет первое перед назначением на f1.

Ответ 2

Это вызвано подъемом. var и function объявляются в верхней части блока script, в котором они находятся.

Это означает, что ваш первый script по существу становится:

var f1;
function MyFunc() {
    alert(1);
}
f1 = MyFunc;

// new script block

function MyFunc() {
    alert(2)
}

// new script block

f1(); // alert 1

Между тем, ваш второй script станет:

var f1;
function MyFunc() {
    alert(1);
}
function MyFunc() { // overwrite previous MyFunc
    alert(2)
}
f1 = MyFunc;

// new script block

f1(); // alert 2

Надеюсь, это имеет смысл - просто избегайте переписывания функций XD

Ответ 3

Для первой части с сообщением 1 объявление var f1 = MyFunc; становится похожим на локальный по сравнению с <script> blocks.Hence блок <script>, в котором var f1 определяется, что он выполняет функция, содержащаяся в этом блоке.

Для второй части с сообщением предупреждения 2, первый MyFunc() перезаписывается вторым.

Ответ 4

Надеюсь, я никого не смучу, но я подозреваю, что ответ имеет какое-то отношение к областям.

Вот мой аргумент:

В первом случае:

 <script type="text/javascript">
    function MyFunc() {
        alert(1);
    }
    var f1 = MyFunc;
   window.foo1 = MyFunc;
</script>
<script type="text/javascript">
    function MyFunc() {
        alert(2)
    }
  window.foo2 = MyFunc;
</script>
<script type="text/javascript">
    f1();
    alert(window.foo2 === window.foo1);
</script>

Второе предупреждение выдаст ложное сообщение.

Теперь второй случай.

<script type="text/javascript">
            function MyFunc() {
                alert(1);
            }
            var f1 = MyFunc;
            window.foo1 = f1;
            function MyFunc() {
                alert(2)
            }
            window.foo2 = MyFunc;
        </script>
        <script type="text/javascript">

        </script>
        <script type="text/javascript">
            f1();
            alert(window.foo1 === window.foo2);
        </script>

Второе предупреждение выдаст значение true.

Это показывает, что (для 1-го случая) MyFunc переопределяется и является совершенно другим "объектом" при обработке второго блока script. f1 содержит ссылку на первый "объект" в первом блоке script. Следовательно, f1() предупреждает 1.