Почему видимость функции 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
.