0

I have a fundamental misunderstanding of how Javascript works, and I hope someone can explain it to me.

Everything works fine if I include a function in a script section in the head and one calling that function in the body.

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script>
        function say_hello() {
            document.write('hello');
        }
    </script>
</head>
<body>
    <script>
        say_hello();
    </script>
</body>
</html>

If I move the same code to the body, I get an error. "Uncaught ReferenceError: say_hello is not defined"

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<body>
    <script>
        say_hello();
    </script>
    <script>
        function say_hello() {
            document.write('hello');
        }
    </script>
</body>
</html>

But it works again if I put the function in the same script area.

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<body>
    <script>
        say_hello();
        function say_hello() {
            document.write('hello');
        }
    </script>
</body>
</html>

A common mantra is to move javascript to the end of the body area of HTML. But when I try to move my javascript functions, this is what happens. What am I misunderstanding?

bookworm
  • 53
  • 1
  • 7
  • 3
    It's being hoisted in the second example. – Spectric Feb 14 '23 at 23:27
  • What exactly do you expect to happen and why? What exactly is your misunderstanding? You should familiarize yourself with scope and hoisting rules: [What is the scope of variables in JavaScript?](/q/500431/4642212), [Javascript function scoping and hoisting](/q/7506844/4642212), [Global functions in javascript](/q/29514382/4642212). I strongly encourage you to move to [JavaScript modules](//developer.mozilla.org/en/docs/Web/JavaScript/Guide/Modules). Also, `document.write` is [not recommended](/q/802854/4642212). – Sebastian Simon Feb 14 '23 at 23:29
  • When the browser hits a script tag (not async or module), it first grabs all the functions from that script tag, then executes the script. (Functions are special wherever they occur in scripts. They get "hoisted" like @Spectric said.) That's why `say_hello()` failed when you put it in a separate script tag above `function say_hello() {}`, but succeeded when you put both in the same script tag, even though it was still above `function say_hello() {}`. – Michael G Feb 14 '23 at 23:33
  • @MichaelG Functions are not special. Variables are also hoisted. – Anton Podolsky Feb 14 '23 at 23:36
  • @AntonPodolsky `console.log( nope === 22, nope in globalThis ); var nope = 22;` Sort of, yes. But uninitialized. – Michael G Feb 14 '23 at 23:39
  • I've done a lot of javascript, and this is honestly the first time I recall hearing the word "hoisted." I'm self-taught. Okay. this makes a little more sense. Thank you. – bookworm Feb 14 '23 at 23:41
  • @MichaelG Variable declaration is hoisted, variable assignment is not, that why you're not getting an error when accessing "nope". You are right though in the sense that function declarations + assignments are hoisted, unlike variables. – Anton Podolsky Feb 14 '23 at 23:42

0 Answers0