-1

I've recently had some trouble wrapping my head around the way javascript behaves when a function is called from an html tag (e.g.: onmouseleave()).

In the following example, bloonClick is called from a div's onclick():

        function bloonClick() {
            const bloon = document.getElementById("balloon");
            let currSize = bloon.clientWidth;

            colourShift(bloon, 1);
            if (currSize <= 420) {
                bloon.style.width = (currSize + 10) + "px";
                bloon.style.height = (currSize + 10) + "px";
            } else {
                bloon.style.width = "200px";
                bloon.style.height = "200px";
            }
        }

        let colourCode = 0;
        function colourShift(bloon, trigger) {
            let colourArr = ["#42c742", "#3232d7", "#d73232"];

            colourCode += trigger;
            if (colourCode < 0) {
                colourCode = 2;
            } else if (colourCode > 2) {
                colourCode = 0;
            }
            bloon.style.background = colourArr[colourCode];
        }

As you can see, colourCode is declared in the global scope and used inside colourShift(). For some reason I don't quite understand this leads to what I consider static behaviour (at least from my C background, static has a whole other meaning related to objects in JS from what I've read), since the value of colourCode is preserved in-between bloonClick() calls.

That by itself is enough to make me confused, but the reason behind this question is that after a bit of testing I found out moving const bloon = document.getElementById("balloon"); to the global scope (which seemed interesting since the same getElementById() is used in another function not present here) not only does not present the same static behaviour, it doesn't work at all.

Can someone please explain why these two things happen?

Thanks in advance :)

  • 2
    "*moving `const bloon = document.getElementById("balloon");` [...] not only does not present the same static behaviour, it doesn't work at all.*" what do you mean by this? – VLAZ Oct 13 '22 at 16:39
  • 4
    Are you trying to set `bloon` before the DOM has loaded? – mykaf Oct 13 '22 at 16:39
  • `the value of colourCode is preserved in-between bloonClick() calls` this is expected, since colourCode is globally scoped. Each time you call colourShift I would expect colourCode to be incremented by trigger. – James Oct 13 '22 at 16:42
  • 1
    Re `colourCode`: It's a global variable, so yes, it's initialized once (when `let colourCode = 0;` is executed) and persists between calls to the other functions, since it's not *inside* those functions. As you said, it's global. There's only one, and it lasts as long as the environment all of this code is running in lasts (for instance, the duration of the page). If I recall my C from 30 years ago correctly, that would be like `static int colourCode = 0;` at the top-level scope of a file, since it's accessible from anywhere and persists. – T.J. Crowder Oct 13 '22 at 16:42
  • @VLAZ I mean if I move that line to, say, right above the declaration of colourCode, bloon isn't initialized, but becomes undefined. I didn't understand this, but Asher's answer cleared it up for me. I'm really new to webdev, so I'm pretty unfamiliar with the terms (just had to look up DOM lol) and the way everything works. – El Nitromante Oct 14 '22 at 08:55
  • @James that's exactly what it does, but as I just said in the comment above I'm new to this, I thought the script was partially loaded as functions were called and finished, but is the script is loaded once and stays as such it does make a lot of sense a global variable would keep it's value. – El Nitromante Oct 14 '22 at 08:58
  • 1
    At least *closely* related: [*Why does jQuery or a DOM method such as getElementById not find the element?*](http://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) and [*What is the scope of variables in JavaScript?"*](https://stackoverflow.com/questions/500431/what-is-the-scope-of-variables-in-javascript). – T.J. Crowder Oct 14 '22 at 09:17

1 Answers1

1

Your code runs as soon as the browser downloads the script (I don't see any event listeners). The two functions are parsed and the variable is declared. colourCode is declared in the global scope, and is accessible from both functions.

When you move const bloon = document.getElementById("balloon"); to the global scope - i'm guessing what's happening is your script is called in the head tag and the script tries to get the element (with id "balloon") before the element is even rendered to the DOM, therefore it does not exist and can't be found. When it's called inside the function (after the user clicks) - the element is already rendered. To fix this you can move your script tag to just before the closing </body> tag.

Asher Moshav
  • 109
  • 5
  • @T.J.Crowder I'm sorry, but I couldn't find any information about it because I really didn't understand what I was looking at, but this answer not only cleared up my question, it also made me understand how web works a lot better. – El Nitromante Oct 14 '22 at 09:01