Search code examples
javascripthtml

JavaScript function redeclaration and hoisting


in this example in the MDN functions article: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Functions

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./script/first.js"></script>
    <script src="./script/second.js"></script>
    <script>
        greeting();
    </script>
    <title>Document</title>
</head>
<body>
    
</body>
</html>
// first.js
const name = "Chris";
function greeting() {
  alert(`Hello ${name}: welcome to our company.`);
}
// second.js
const name = "Zaptec";
function greeting() {
  alert(`Our company is called ${name}.`);
}

why does the first greeting function execute but if i change the const name to just name

// second.js
name = "Zaptec";
function greeting() {
  alert(`Our company is called ${name}.`);
}

the second greeting method is executed?

my current understanding is that in the second case the greeting function in second.js is hoisted to the top so it overrides the first greeting method before the exception is thrown and the script is stopped but why doesn't this happen in the first case?


Solution

  • Because the first error is a SyntaxError which happens before hoisting, while the second error is a TypeError which happens after hoisting.


    The first case results in a SyntaxError: Identifier 'name' has already been declared caused by the second const name = ... line.

    If you removed both const keywords, it "works" but actually changes the global window.name variable.

    However, if you only remove the second const keyword, you get a different error: TypeError: Assignment to constant variable., and indeed it does use the second greeting definition, but with the first name!

    You may wonder, why does the second case behave differently? It's because the SyntaxError happens while the file is parsed (only read, not executed yet). It fails at the first line and stops processing the rest of the file. On the other hand, the TypeError happens at runtime, during execution. At this point, the hoisting already took place! The second greeting was already moved up and the new function definition was already executed, overriding the previous one. Only afterwards, the const name = ... got executed and failed.


    Recap:

    First case (const in both files): Second file fails to parse with a SyntaxError. Nothing executes in that file.

    Second case (const only in first file): Second file succeeds to be parsed, greeting is hoisted. Execution starts, the hoisted greeting definition is applied, then the const name = ... fails to execute with a TypeError and further execution stops (but there is nothing to execute there anymore anyway).