First pass

The first thing I notice (thank you syntax highlighting) are the keyword of the script:

Those are the ones in this script, there are many more and each one is related to important topics that you'll need to learn sooner or later.

Let's focus on the first two right now: let and const. These are the keywords used to declare and assign variables. Now, what is the difference between those two?

The first thing I notice, from the first three lines in the script, is that the ones with let are given a value of "", that means it's an empty string, while the one at the top is given a more complex value that involves another keyword: document, and a function. That is not related to whether it's a variable or a constant, but to the datatype assigned to them. Both currentInput and lastResultare strings, which is a 'primitive' datatype, like 'number' or 'boolean' (we'll talk about those later), while displayis an 'object', a non-primitive, that is to say, a complex kind of "thing" that can have different values inside of it and even functions attached to it.

But that is not always the case with constants. And even if you see something like const result = eval(currentInput), which seems complicated, the value in the end is just a number; and a couple lines below, where it says currentInput = String(result), the result is the same value, but in the form of a string. You can test this by adding the following lines just below the ones that says currentInput = String(result), then refresh the page and do a simple operation and look ath the console:

console.log(`${result}: ${typeof result}`);
console.log(`${currentInput}: ${typeof currentInput}`);
// Those are backticks, by the way, not single quotes.

The second thing I notice is that the ones with let are referenced several times with =, that means their value is assigned and re-assigned many times (and also, this is not something a newbie might notice at first sight, but it's relevant: it's not only in the script itself, but also every time the functions that reference those variables get called, every time you click a button on the UI).

In contrast, the ones with const get declared and assigned only once, but referenced many times --don't be confused by the ===, that is a (strict) comparison operator and it doesn't modify modify the value. So, you get why it's called a 'constant', right? If you were to try to change the value of display anywhere else in the script, it wouldn't just break the functionality of the script, the console would throw an error just for trying. So in some cases it's really important that a constant stays constant, in other cases, it's a matter of taste; for example, you could change the const in const result = eval(currentInput); for let and the program is essentially the same.

One last thing you might notice is where in the program each variable or constant gets declared. What happens if you try to add the same two console.log()statement we added before, but somewere else outside of that function? (Do it one by one, so the result is clearer).

For example, add console.log(currentInput); at the end of the file and every time you refresh the page, it'll print ": string", because the variable was pre-declared and assigned an empty string as value at the start.

But what happens if you do the same for result? It'll print an error telling you that result is not defined. Even if you put that statement inside the same function, but outside of the block where it was declared, like at the end, under the updateDisplay(); you'll notice that there is no error now when you refresh, but as soon as you do any operation, you get the same error; if you kept the two statements inside the try statement from before, something even weirder happens: first it prints the value of result and its data-type, and then it tells you it's not defined... huh?

The answer is: Scope

Imagine the program is a set of boxes: one big box outside, inside of that there are four medium-sized boxes, inside one of these boxes there is another smaller box with three tiny boxes inside. If you start in the outemost box, you can go anywhere, including inside any of the smaller boxes, but if you start in one of the inner boxes, you can only go to a lower level box, but not to any other outside of your own box. currentInput was defined in the outermost box, so it can go to any part of the program, while result was declared in one of the innermost boxes, so it can't go anywhere except it's own tiny box. In other words, to the rest of the program, it doesn't even exist. The outer box is the global scope, the inner boxes are function or block scopes. And that's scope in a nutshell.