14

I'm hoping someone can explain to me why the below JavaScript/HTML will show "door #2" when the HTML is viewed in a browser:

<!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>

Since only the declaration testprint occurs before window.onload is set to testprint, I would expect window.onload cause 'door #1' to show up. Actually, onload causes 'door #2'. Note that it will do this whether the first declaration of testprint is included or not.

The third and fourth declaration of testprint use different means of assigning the function, I tried this to see if it would override window.onload's behavior in the same was the second declaration of testprint does. It did not. Note that if I move the fourth declaration of testprint to the end of the first script block it would be called by window.onload.

0

3 Answers 3

39

Function declarations are subject of hoisting, and they are evaluated at parse time, by hoisting means that they are available to the entire scope in where they were declared, for example:

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

The first call to foo will execute the function declaration, because at parse time it was made available, the second call of foo will execute the function expression, declared at run-time.

For a more detailed discussion about the differences between function expressions and function declarations, check this question and this article.

Sign up to request clarification or add additional context in comments.

1 Comment

There is one subtlety to function hoisting where browsers disagree. SpiderMonkey will not hoist functions declared in a conditional scope while V8 (at the time of writing) does so.
1

The reason #3 doesn't change window.onload is that functions are called by reference, not by name. When you set window.onload = testprint, it assigns reference to the current value of testprint (door #2, as explained by CMS) to window.onload. Changing testprint's value later doesn't affect window.onload's value.

Door #4 doesn't override door #2 (unless, as you said, you move it to the first script block) because it's in a different script block, so it gets parsed after the first block is completed.

Comments

-1

function testprint is global to the page. the testprint = function... assigns a variable, that I'm not sure exactly the entire scope of, but I get the idea that it's not added to the function table dictionary the way the first one is.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.