Ссылка на значение JavaScript до его объявления - кто-то может объяснить это

Я надеюсь, что кто-то может объяснить мне, почему приведенный ниже JavaScript/HTML будет показывать "дверь № 2" при просмотре HTML в браузере:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <script type="text/javascript">
        function testprint() {
            alert('door #1');
        };

        window.onload = testprint;

        function testprint() {
            alert('door #2');
        };

        testprint = function() {
            alert('door #3');
        };
    </script>
    <script type="text/javascript">
        function testprint() {
            alert('door #4');
        };
    </script>
</head>
<body>
</body>
</html>

Так как только декларация testprint происходит раньше window.onload установлен в testprintЯ бы ожидал window.onload вызвать "дверь № 1", чтобы показать. На самом деле, нагрузка вызывает "дверь № 2". Обратите внимание, что это будет сделано, будь то первое объявление testprint включен или нет.

Третья и четвертая декларация testprint использовать разные способы назначения функции, я попробовал это, чтобы увидеть, если она переопределит window.onloadТо же самое было второй декларацией testprint делает. Это не так. Обратите внимание, что если я переместить четвертое объявление testprint до конца первого блока скрипта он будет вызван window.onload,

3 ответа

Решение

Объявления функций являются предметом подъема, и они оцениваются во время разбора, путем подъема означает, что они доступны для всей области, в которой они были объявлены, например:

foo(); // alerts foo
foo = function () { alert('bar')};
function foo () { alert('foo');}
foo(); // alerts bar

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

Для более подробного обсуждения различий между выражениями функций и объявлениями функций, проверьте этот вопрос и эту статью.

Причина #3 не меняет window.onload в том, что функции вызываются по ссылке, а не по имени. Когда вы установите window.onload = testprint, он присваивает ссылку на текущее значение testprint (дверь № 2, как объяснено CMS) для window.onload, изменения testprintзначение позже не влияет window.onloadценность.

Дверь № 4 не переопределяет дверь № 2 (если, как вы сказали, вы не перемещаете ее в первый блок скрипта), потому что она находится в другом блоке скрипта, поэтому она анализируется после завершения первого блока.

Функция testprint является глобальной для страницы. testprint = function... назначает переменную, в которой я точно не уверен, но я понимаю, что она не добавлена ​​в словарь таблицы функций, как первая.

Другие вопросы по тегам