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

Я надеюсь, что кто-то может объяснить мне, почему приведенный ниже 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 ]

38 голосов
/ 10 ноября 2009

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

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

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

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

0 голосов
/ 10 ноября 2009

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

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

0 голосов
/ 10 ноября 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...