Second Pass - Notes
1
Notice all the constants at the top and do not confuse them with values that do change. You might think that something like guessInput or attemptsLeft would be variables, but this constants are not pointing to the value in the input fields, they are just pointing to the HTML elements that contain them.
2
In const guess = Number(guessInput.value); notice the 'type conversion'. 'Coercion' is when JavaScript automatically converts a value's data type, like when you add "2" + 2 it automatically converts the 2 to a string and concatenates it, so the result is "22", but if you do "2" / 2, the result is 1 because it automatically converted the "2" to a number. 'Conversion' is when you explicitly do it. In this case this is important because it is later compared to the 'secret number' in the line if (guess === secretNumber). Notice the strict comparison operator '==='; this operator makes sure the two values also have the same type, it's good for security to do this in most cases; '==' coerces the type if it can and compares the values without strict equality.
3
In the very first line of the script we use the 'Math Object' to create a secret number with the Math.floor method. The Math Object is a static object available directly in the language (it made me think of Python "modules", but here you don't have to import anything), and it has a huge list of constants and equations useful in all types of scenarios. It's not a bad idea to familiarize yourself with what's in it.
Let's break down the operation a bit, because the +1 is confusing.
Math.random()returns a floating point (decimal) number between 0 (inclusive) and 1 (exclusive). So the* 100is there to make it something between 0 and 99 instead of between 0 and 0.999999999.Math.floorrounds a number down to the nearest integer. So if you doMath.floor(0.999)the result is0; that's why the* 100has to be evaluated before this, and because it always rounds down it'll return a random number between 0 and 99, so we add+ 1to make sure it excludes 0 and includes 100.
Those are two of the most widely useful methods from 'Math', or the ones I've seen more often. Another common one is Math.abs which returns the absolute value of a number, that is, it removes the - if it has one, so Math.abs(-5) == 5 or Math.abs(3 - 4) == 1 —I remember seeing this one often when doing game coding YouTube tutorials, useful for calculating the distance between two objects in a grid. There is also Math.round() which rounds the number in a more conventional way; we could have used this one, but I suppose it's a better practice to make everything explicit to avoid confusion. And also Math.max() and Math.min() which return the highest and lowest number (respectively) from the list of numbers you give them as parameters. The rest are very specific, but I'm sure they have their usefulness in some context, I just haven't come across them. Interestingly, there are also a number of constants there, like Math.PI or Math.E which is "Euler's number", or "The base of natural logarithms"; or Math.LOG2E which "returns the base-2 logarithm of E." I have no idea what any of that means or in what context I might use it...
Moving on...
4
The only function we are declaring and naming here is the endGame() function at the end, which gets called when the player runs out of guesses without having found the number or when he finds the number. It does a bit of interesting DOM manipulation: first it disables the input and the 'guess' button by directly accessing the disabled attribute of guessInput and guessBtn and setting it to true; then it accesses the 'style' attribute of resetBtn and sets the display property to inline block, making the button appear as if out of nowhere.
The other two functions are the anonymous arrow callback functions passed and defined as arguments of the addEventListener method on each of the buttons. If you ask me, this kind of functions defeat the purpose of the definition of function we learn at first when they tell you that functions are "reusable" blocks of code, but anyway... The most important part of 'callback functions' is that they get executed after the rest of the code in the function, they are very important for asynchronous programming. So the method addEventListener defines a bunch of <a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener" target=_"blank">instructions and then "listens" for a click event, and when it happens, the code inside the callback gets executed.