How JavaScript Works
Are you totally new to JavaScript and the only “programming” background you have is HTML and/or CSS? Odds are that JavaScript will feel pretty different to you.
This explanation might help you get the basics of how JavaScript works, which will be fundamental as you move forward. Consider this your “A-B-C”s look at JavaScript.
A Sequence of Steps
The first thing to know about JavaScript is that its job is to tell the computer how to do something step-by-step. Think of it as a “tutor” for the browser, telling it to “Do this. Now do that.”
We use the word statement to describe the idea of a complete instruction (whether simple or complex). In other words, it’s a single step that we want our computer to perform.
It’s not just about instructions, though. It’s also about information. The instructions are there in order to do something with or to some piece of information. We hold or represent information in something called variables.
Code Samples
The following code illustrates Simple Sequence. It’s a step-by-step approach to calculate the perimeter of a rectangle. Here, we’re making our steps ultra-small, to illustrate the sequence. We’re giving the browser instructions to execute, one after the other.
// We want variables to hold informationlet leftSide; // The rectangle's left sidelet topSide; // The rectangle's top sidelet perimeter; // For the final result
// Now we need our initial informationleftSide = 3;topSide = 4;
// Time to do some mathperimeter = leftSide + leftSide + topSide + topSide;
// Display the resultconsole.log('The perimeter is:', perimeter);// output: The perimeter is: 12
One of the big consequences of simple sequence is that certain steps must happen before others. For example, you must have values assigned to leftSide
and topSide
before you to try to calculate the perimeter
.
Another aspect is that later changes to a variable’s value won’t affect prior calculations. Consider this example.
let total;let quantity = 10;let price = 5.95;
total = quantity * price;console.log('The total is:', total);// output: The total is: 59.5
quantity = 20;console.log('The total is still:', total);// output: The total is still: 59.5
Contrast that with CSS which uses entirely different rules when applying styles. In the following stylesheet, the last border style overrides (replaces) the previous one.
h1 { font-size: 3rem; border-left: 1px;}
/* ... more styles ... */
h1 { border-left: 5px; padding-left: 3px;}
Bundles of Instructions
The second thing to know about JavaScript is that it allows us to create functions. Think of functions as small sets of instructions dedicated to accomplish some specific task. The benefit of functions are two-fold:
- They give us the benefit of re-use, because we can call our functions as often and wherever we want.
- They allow us to focus around individual tasks or goals.
To give you an idea of how essential functions are, all JavaScript environments come with hundreds of built-in functions. They include functions that
- Manipulate text and numbers,
- Perform complex math operations,
- Work with dates, and
- Manipulate arrays.
That’s a short list of categories, and each one can contain dozens of functions we can call upon to get jobs done.
For a concrete example, consider the fact that all user input/output comes in textual form. That’s true even when we are asking the user to give us a number. That means we need some function that can convert from a string to a number. Consider this code snippet based on the “Hitchhiker’s Guide to the Galaxy”1. It uses the parseInt()
function.
// According to the "Hitchhiker's Guide to the Galaxy" the expected input is '42'let input = prompt("What's the answer for life, the universe and everything?");let answer = parseInt(input); // Changes '42' into 42
We’re not limited to the functions that come with JavaScript. We can create our own!
Declaring vs. Calling
A function declaration is where we state exactly what our function will do. Here’s a sample.
const promptPerimeter = function(openingName) { let textInput = prompt(`Enter the height for ${openingName} (in inches).`); let height = parseInt(textInput); textInput = prompt(`Enter the width for ${openingName} (in inches).`); let width = parseInt(textInput); return height * 2 + width * 2;}
It’s not enough to declare our function. We would need to also call our function. Imagine that we wanted to get the amount of wood to frame a set of three windows for a room.
let totalLength = promptPerimeter('the North window');totalLength = totalLength + promptPerimeter('the East window');totalLength = totalLength + promptPerimeter('the West window');console.log('The total length (in inches):', totalLength);
Without functions, our code could potentially grow to an unreasonable (and un-maintainable) size. Here’s what we would need to code if we couldn’t make our own functions.
// We want variables to hold informationlet textInput; // All input comes in as stringslet height;let width;let totalLength; // For the final result
// Get the first window detailstextInput = prompt("Enter the height for North window (in inches).");height = parseInt(textInput); // e.g.: changes '22' into 22textInput = prompt("Enter the height for North window (in inches).");width = parseInt(textInput);
totalLength = height * 2 + width * 2;
// Get the second window detailstextInput = prompt("Enter the height for East window (in inches).");height = parseInt(textInput); // e.g.: changes '22' into 22textInput = prompt("Enter the height for East window (in inches).");width = parseInt(textInput);
totalLength = totalLength + height * 2 + width * 2;
// Get the third window detailstextInput = prompt("Enter the height for West window (in inches).");height = parseInt(textInput); // e.g.: changes '22' into 22textInput = prompt("Enter the height for West window (in inches).");width = parseInt(textInput);
totalLength = totalLength + height * 2 + width * 2;
// Output the result;console.log("The total length (in inches):", totalLength);
That’s a lot more code! Without the ability to make our own functions, our code would grow exponentially if we wanted our program to accomplish more than it currently does.
Control Flow
It’s not all simple-sequence and method calls when it comes to the execution of our code. Often times we want our program to choose different paths of logic or to do things repeatedly. We can write those kinds of instructions with “If/Else” and looping structures.
This third aspect of JavaScript programming is all about Flow Control - deciding which instructions to execute.
Conditionals
The idea of a conditional is to provide our code with Alternate Paths of Logic during execution. Essentially, we can introduce a “condition” as some decision that can be made as the computer is executing our code. Based on whether the condition is true
or false
, certain code will run while other code will not.
The if...else
statement in JavaScript allows us to set up a test (or condition) to determine if we want to run certain code. For example, consider the fact that Math does not allow division by zero. We might have code like this.
// imagine some code above has obtained input from the userif (count > 0) { average = total / count;}
This tells the computer to only compute the average when the count is greater than zero. If the value of count is zero (0
), then the average will not be computed, thus avoiding the division by zero error. (Additionally, we’re avoiding negative count
values because a negative average typically doesn’t make sense).
Notice how the code inside the curly braces will only run if the condition - (count > 0)
- is true
. The if
statement also offers an optional else
side to allow us to do something when the conditional expression produces a false
result.
// imagine some code above has obtained input from the userif (count > 0) { average = total / count;} else { console.log('That is an invalid count:', count);}
Loops
The idea of a loop is to execute one or more lines of code more than once. Whereas a conditional statement allows for alternate paths of logic, loops allows for Repetition of logic. Like the if...else
examples above, the thing that controls the repetition is some conditional expression or decision.
While Statements
There are many looping statements in JavaScript. The oldest, and most general-purpose, is the while
statement. As a simplistic example, consider the following code. It outputs the numbers 1 through 10 to the console.
let count = 1;while (count <= 10) { console.log(`Item ${count}`); count = count + 1;}
The conditional expression - (count <= 10)
- controls the repetition of the code inside the curly braces. As long as that expression results in a true or truthy value, the code will repeat. Also note that the value of count
is modified inside the curly braces. Each time through the loop, its value increases by one, until it ultimately holds the value 11
. At that point, the conditional expression results in a false
, causing the loop to exit.
For Statements
Another popular looping statement is the for
statement. Look again at the code for the while
statement. Notice how there are three instructions that control the repetition:
let count = 1
- Creates the variable and gives it an initial valuecount <= 10
- The conditional expression controlling entry to the code in the curly bracescount = count + 1
- Changes the value of the variable tested in the conditional expression
let count = 1;while (count <= 10) { console.log(`Item ${count}`); count = count + 1;}
The for
statement brings all three of these instructions into one place, making it easier to see what affects execution of the code in the curly braces.
// An alternative to our while statementfor (let count = 1; count <= 10; count = count + 1) { console.log(`Item ${count}`);}
Looping structures are a powerful way to control the flow of execution of our code. These, along with conditional statements, are great candidates for use inside of functions.
Displaying Results
We don’t use JavaScript in a vacuum. JavaScript - in its most common use - is in support of our HTML content. We often want to display the results of our work to the user. It might be in an overt way (e.g.: modifying content on the page) or it might be in subtle ways (e.g.: changing styles or applying CSS classes).
This is the part where JavaScript interacts with something outside of itself. Remember that JavaScript, as an interpreted language, is being executed by the web browser. The browser makes the web page available to our JavaScript code through a “global” variable - the document
object.
The document
object is a very complex representation of everything on the page. It’s referred to as the Document Object Model, or DOM. Through that document
object we have access to functions that allow us to find individual parts of our page. Once we can access those, we are then free to modify them. We can even add or remove parts of our page entirely through the DOM API functions!
Here’s a simple example. This code creates a variable that will reference or point to the first <h1>
element on our page. Using that variable, it applies a CSS style to change the appearance of the element.
let h1Tag = document.querySelector('h1'); // Find the first <h1>h1Tag.classList.add('hover-sparkle'); // Give it a CSS class
Event Handling
The last significant way JavaScript supports our HTML is by allowing users to interact with our web page. This is accomplished by listening to events.
We can write code that instructs the browser to run certain functions when various events occur. For example, a user might click on some part of our page, like a heading or a button. Or they might submit a form. Another example is that they might want to select and drag one part of the page onto another part of the page.
let myList = document.querySelector('ul#priority-list');myList.addEventListener('drag', moveItem);
The tutorial Intro to Event Listeners is a great introduction to creating interative user experiences.