Second Pass

Now I want to focus on the next keyword from the list we compiled: function.

Functions, in JavaScript, and in any other programming language are, of course, a very big, complicated and important topic, so it's something we'll keep learnig about, but there's no rush.

Now, I see the keyword function three times, that means we are declareing three functions: handleValue(value), handleAction(action) and updateDisplay(). Each function is a set of statements or instructions that get executed when they get called, when a certain event happens or condition is met.

But what can get confusing is where exactly are these functions called. They are never just called straight from the top level of the program. Two of them, handleValue and handleActionare called from within the block that start with document.querySelectorAll(".btn") and the third one, updateDisplay() is called from within the other two functions. If the ".btn" looks familiar it's because it's directly referencing the class btn from our HTML file, in a similar way to how the first line references the element with the id display from the HTML. But anyway, what does this block do? The clue is in the next line, the addEventListener, like it's name suggests, it listens for events... but what event, you ask? It's right there inside the parenthesis: "click". So it "adds" something that "listens" for "click events", to every element with the "btn" class to do some actions when the click happens.

Let's break it down further like this:

I just mentioned undefined, that just means that it doesn't have a value, even though it exists. When the constants are declared above, the program goes and searches the html tag for a value to assign to them. If it finds "data-value", then it assigns it to value, and if it finds "data-action" then it assigns it to action. To see that in action is very easy, add a couple of lines below the constants' definitions:

console.log(value);
console.log(action);

This will just print the value of both constants when a button is clicked. Open the console again and click on any button (don't forget to refresh the page first). If you click on a number button or an operator you'll see the console prints the number or the operator, followed by "undefined"; if you click on an action button, for example, the "=" button, you'll see first the line that says "undefined" and then "calculate".

So all this block does is assign the correct value to each button only when it is clicked and then decide which function to call.


A brief word about arrays:

In every coding tutorial out there, very early on you get a section about arrays. And they tell you "You define an array like this... these are the indexes and this is how you print the value at index number 0... and so on"; but then when you are out there in the wild, looking at real code, you rarely encounter an array explicitly defined like that. Instead, what you get, I've noticed, is arrays that are defined "on the fly" by another function, such as querySelectorAll that just takes data from some place else --could be an api, a database, or, like in this case, the HTML document. You never see the array neatly defined like array = [1, 2, 3, 4] because the array itself is not important, what's important is what you do with the data in it.

You can see our "array" if you type this command in the console:

document.querySelectorAll(".btn").forEach((btn) => { console.log(btn) });

It'll print the whole html tag for all the buttons.

forEach() is an array method that iterates over each item in an array and performs a function for each item. You can see it in a more straight-forward way by typing this in the console:

[1,2,3].forEach(alert);

It'll succesively open three popups with 1, 2 and 3. alert() is the function here, it's parameter is the value of the item given to it by the forEach() method when it calls alert() once for each item.


Wait, so then, which one's the function in the first example, is it the (btn)? No, see the => thingy that looks like an arrow? That is what's aptly called an "arrow function", the part in the parenthesis is just the parameter to the function, and the part between the curly braces, { }, is the body of the function. The arrow basically just replaces the function keyword.

Back in our script, we have two arrow functions in the block that starts with document.querySelectorAll, one after the other. Both are anonymous callback functions. (Callback just means that the function is passed as a parameter to another higher order function). The first one is similar to the example above and within the body of that one we have another arrow function as a parameter to the method addEventListener, this arrow function doesn't take any parameters and within it's body is where we define the constants value and action and where we have the if statement and the call to handleValue() or handleAction.

This new arrow function is triggered when the "event listener" detects a "click" event. There are many more "events" that can be used for different functions --there's a whole list of them somewhere in the docs--, a very common one is DOMContentLoaded; but if you want to turn your normal-ass calculator into a crazy calculator, go ahead and replace the "click" with "mouseenter" and see what happens!