It’s time to unlock what JavaScript can do when it’s not just a calculator. We’ve skipped over a lot of details about data types to get to here, but it’s important to start thinking programmatically as soon as possible. Rules and properties we can always look up. How to do things programmatically, however, is a skill that needs to be nurtured. As a result, it’s a source for early frustrations as well. Just remember, programming is puzzle solving, and in this part of the process you can finally start thinking of the puzzle as a journey.
Control flow
Control flow is an idea you’ve probably seen before, like in flow charts. They’re all over social media and often funny. In a flow chart, you start from some position and answer questions. Depending on the answers to those questions, you end up in a certain location. Other answers lead you somewhere else. But the idea is that you are interacting with information, in that you are being provided a prompt for some input, and your input directs what happens.
Let’s sketch out a toy program to begin illustrating control flow in a program.
We want to write a program that asks the user what they want for dinner. If
they answer “burrito,” the program congratulates their choice. If they answer
anything else, the program scolds them for not wanting a burrito. What might
that look like in pseudocode (pretend programming that’s not a real
language)? Let’s try it out while also using some JavaScript we already know,
like let
and console.log()
.
First, the program needs to get the information from the user, so we need some kind of input. Let’s save that as a variable.
// THIS IS PSEUDOCODE. It is for illustration only. It will crash.
//
let userInput;
userInput = prompt_the_user_for_what_they_want_for_dinner;
We have a variable now, userInput
, that has whatever the user has input. Now
let’s test that variable, using the ===
operator you’ve already learned.
// THIS IS PSEUDOCODE. It is for illustration only. It will crash.
//
if userInput === "burrito";
then console.log("Brilliant choice!");
OK. But what if the input isn’t “burrito”?
// THIS IS PSEUDOCODE. It is for illustration only. It will crash.
//
if userInput !== "burrito";
then console.log("Don’t you want a burrito?");
Here I’m using the negation operator !==
. It’s the same as ===
, but its
inverse.
And that’s it. We have our program. The JavaScript, as we’ll see, isn’t so terribly different from this code we already have.
If statements
An if statement is an example of conditional statement. That means that it behaves in a certain way depending on a condition. From the example above, we can read
// THIS IS PSEUDOCODE. It is for illustration only. It will crash.
//
if userInput === "burrito";
then console.log("Brilliant choice!");
As “If the condition that the variable userInput
is equivalent to the string
‘burrito’ is true, then respond to the console the string ‘Brilliant choice!’”
That’s a mouthful, but it is actually three distinct steps:
- The test of whether
userInput
is equivalent to the string “burrito.” - If the test in 1. is
true
, then the condition in the if statement is met, so we can go on to 3. - log to the console the string “Brilliant choice!”
Now, JavaScript’s syntax is different from the pseudocode above. First, there
is no then
statement. Instead, that then
is replaced with braces ({}
).
Everything within the braces gets executed if the truth test (userInput ===
"burrito"
) returns true
. And the truth test itself is surrounded by
parentheses. Generically, then, it looks like this:
// This code is for illustration only. It will crash your console.
//
if ( truth_test ) {
do_things_if_the_test_returns_true;
}
Note where the semicolons are (and are not!) in this example. Now we can fill
it out with some of our toy program. We know that do_things…
is actually
console.log("Brilliant choice!")
, so we can put that in. As for
truth_test
, let’s just put in true
for now.
> if ( true ) {
console.log("Brilliant choice!");
}
//--> Brilliant choice!
Type this into the console (pressing the return key where appropriate). You
should get “Brilliant choice!” logged to your console. Now replace true
with
false
. What happens? Why?
Now you can add some complexity, this time using the variable userInput
:
> let userInput;
> userInput = "burrito";
> if ( userInput === "burrito" ) {
console.log("Brilliant choice!");
}
//--> Brilliant choice!
Notice where you have to use =
(which assigns a value to a variable) and
where you have to use ===
(which tests whether something is true). If you
type this in the console, again it should congratulate you. If you replace the
second line with userInput = "samosa";
, what happens? Why?
In our program, we had a second condition, which would scold the user if they didn’t want a burrito. That’s pretty straightforward to write:
> let userInput;
> userInput = "samosa";
> if ( userInput !== "burrito" ) {
console.log("Don’t you want a burrito?");
}
//--> Don’t you want a burrito?
However, we can join both truth tests using else
:
> let userInput;
> userInput = "samosa";
> if ( userInput === "burrito" ) {
console.log("Brilliant choice!");
} else {
console.log("Don’t you want a burrito?");
}
//--> Don’t you want a burrito?
Now, we can see this as “if the truth test is true, then log ‘Brilliant choice!’ Otherwise, respond ‘Don’t you want a burrito?’” Less typing! If you type this snippet into your console, you’ll see that it scolds you. What do you have to change so that it congratulates you?
So far so good, but we still have the line of the pseudocode, userInput =
prompt_the_user_for_what_they_want_for_dinner;
. Getting that part to work
requires writing some HTML.
Embedding JavaScript in a webpage
Typing things into the console becomes tedious to have to retype everything every time. Fixing mistakes is difficult. And if you close the window (or reload your browser), you lose everything you’ve already done. There must be a better way to write and execute JavaScript, right? Of course there is.
Back in Chapter one, I had you clone a project with Atom,
and that project included a file called index.html
. Open that file up in
Atom by double clicking on it in the Projects tab on the left of the Atom
window. Now we need to open this file in a browser, as well. This is a bit
tricky, but if you look at the title bar for Atom, it should say something
like “Project — ~/github/javascripting-english-major-project.” That means the
file is in a folder, called javascripting-english-major-project
. That
folder, in turn, is in a folder called github
, which is in your home folder.
On Windows, it’s saved somewhere else.
Open up your home folder, like you would to open up any kind of regular
folder, and you should see the github
folder. Open that up, and you should
see a folder with your repository. If you open that up, you’ll see the file
index.html
. Double click on that, and it should open up in your browser.
It’ll be boring, but it’ll be there. You should be greeted with a blank white
webpage with, in large text, “This is my project!”
For the rest of this course, we will be using Atom and a web browser, so it’s time to get used to having both open at once. Back in Atom, change the text “This is my project” to something else and save your change. Switch over to the browser and press the reload button. The text should change.
Congratulations, you are now a web editor.1 Let’s make you a web developer,
though. That involves adding a few lines to index.html
, so go back to Atom.
Inside the <body>
tags, underneath the <h1>
, add:
<div id="response">This is the #response div.</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="scripts.js"></script>
Type that second line carefully. When you’re done, the whole of index.html
should look like this:
<!doctype HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My JavaScripting English Major Project</title>
</head>
<body>
<h1>This is my project!</h1>
<div id="response">This is the #response div.</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="scripts.js"></script>
</body>
</html>
Save and commit, like you learned earlier. A good commit message would be “Add jQuery and local JavaScript.”
There are two new tags here, <div>
and <script>
. The first is a generic
container tag that lets you mark off a part of a page for content. Note that
it has an id
attribute, and the value of that attribute is response
.
Throughout, I’ll be referring to this <div>
container as #response
. The
second tag, <script>
, tells the webpage to look for files indicated by the
src
, or source, attribute. In other words, first it goes to a web
server, code.jquery.com
, and downloads a source file from there, called
jquery-3.2.1.min.js
. Then it looks for a local file, on your computer,
called scripts.js
. But that file does not yet exist. So now you can make
it.
Back in Atom, right-click (or control-click) on your project icon and choose
“New File” from the dropdown menu. A tiny window asking for the file’s name
will appear, and you should type in scripts.js
. In the new window that
opens, type in:
alert("scripts.js has loaded!");
Save the file and reload the browser. You should get an alert, telling you
that “scripts.js has been loaded!” If you do, stage and commit. A good commit
message now would be “Create scripts.js.” In the project pane in Atom, you
should see scripts.js
alongside index.html
.
That’s obviously pretty annoying, so change alert
in scripts.js
to
console.log
. Now open up the console on the browser and reload the page. As
you can see, instead of typing JavaScript directly in the console, we can type
it in Atom, instead, and reload our page. But even writing to the console
isn’t terribly interesting, except when you’re testing or debugging. Let’s use
JavaScript, instead, to write to the webpage itself.
There are a lot of ways to do that, but that <script>
line about “jquery”
above will make things a bit easier. jQuery is a powerful
JavaScript library, meaning it is a set of tools that make programming
easier. It lets us developers do many tasks succinctly and clearly. Replace
your single line in scripts.js
with this, then:
$("#response").html("scripts.js has loaded!");
Now reload the page in the browser. That earlier text, that read “This is the #reponse div.” is now replaced. We’ll learn jQuery in greater detail as we move along, but that one line of JavaScript does this:
$(
: Select something in the webpage with jQuery."#response")
: In fact, select the HTML element with theid
ofresponse
. (The#
means are looking for something with a specificid
.).html(
: Do something with the HTML that is inside the element we selected."scripts.js has loaded!");
: Change the HTML with this new HTML.
The jQuery selector, $("")
, is
one of the most important bits of code on the web.2
Catch your breath. A whole lot has happened in this section. Let’s return to
the toy program from the previous section, though, and update the
console.log()
parts with the jQuery. In other words, make your scripts.js
file look like this:
let userInput;
userInput = "samosa";
if ( userInput === "burrito" ) {
$("#response").html("Brilliant choice!");
} else {
$("#response").html("Don’t you want a burrito?");
}
Save and reload in the browser. What happens now? What if you change “samosa”
to “burrito” in scripts.js
, save, and reload?
We’re back to where we were at the start of this section, but now instead of logging information to the console, you’re changing text on the webpage. Yet there’s still that little detail about how to ask the user what they want for dinner.
In other words, we want to change userInput = "samosa";
in scripts.js
to userInput = prompt_the_user_for_what_they_want_for_dinner;
, but in
JavaScript, not pseudocode.
There are a lot of ways to get information from the user, but for now we can
use JavaScript’s prompt()
function, which asks the user to type something in.
This works on most browsers, but some (like Brave) might have it disabled.
Change the second line of scripts.js
to:
userInput = prompt("What do you want to have for dinner?", "Type your answer here.");
Save and reload. If all goes well, when you reload the page in the browser, you should immediately have a teeny window asking you what you want for dinner. No matter what you type in, unless it’s “burrito,” the webpage will scold you. If that works, commit.
You’ve written a full program. It takes in input, feeds it through control flow (in this case, a conditional statement), and delivers output appropriate to the input. Of course, it’s still pretty basic, but baby steps. Baby steps.
While and for loops
If you’ve got conditionals down, we can now move to looping. Remember, in JavaScript, a conditional statement takes the form of:
// This code is for illustration only. It will crash your console.
//
if ( some_condition_is_true ) {
do_things;
}
Loops use the same syntax:
// This code is for illustration only. It will crash your console.
//
while ( some_condition_is_true ) {
do_things;
}
for ( complicated_stuff_we’ll_get_to ) {
do_things;
}
While loops
While loops keep executing over and over until the truth test becomes false. As a result, something like:
while ( 0 < 1 ) {
console.log("Zero is less than one.");
}
will keep running forever or until your browser crashes. Whichever comes first. As you can see, the while loops can be dangerous if the truth test never stops being true. An if statement gets executed once and moves on. Loops, though. Well, it’s in the name!
Yet it’s possible to use while loops with a bit of discretion. For example,
replace the contents of scripts.js
with this:
let i;
i = 1;
while ( i < 4 ) {
$("#response").append("<br />" + i);
i = i + 1;
}
Before saving and reloading the webpage, what do you think this does? Now when you reload the page and see what it does, can you figure out why? If yes, then looping already makes sense to you, and you’re a step ahead. If no, I’ll walk through what’s going on here step by step:
let i;
i = 1;
First we define a variable i
and assign it the number 1. It’s tradition in
programming to call looping variables i
, so I’m continuing that
tradition.
while ( i < 4 ) {
Read that out in English: “while the variable i is less than the number four.”
That means that as long as i
is less than 4, the loop will be true, and
the program will loop.
$("#response").append("<br />" + i);
This line is a bit sneaky. First, it uses .append()
instead of .html()
.
That just means that it adds the HTML to the end the already existing HTML
instead of replacing all of it. Next, it uses <br />
, which is the HTML tag
for making a line break. But note that little i
at the end. We’ll come back
to it in a second, but for now it should be clear that this line means “append
the HTML line break tag and the value of the variable i
to the HTML element
#response
.”
i = i + 1;
}
Finally, and this is what gives the loop its magic, we see this expression. In plain English, this means, “assign to the variable i the value of the variable i plus 1.” This may seem like nonsense. After all, you can’t have “x = x + 1” in algebra class, which is probably the last time you dealt with variables. But in programming, this is allowed. And, in fact, it’s super useful.
Let’s look at the program in its entirety again:
let i;
i = 1;
while ( i < 4 ) {
$("#response").append("<br />" + i);
i = i + 1;
}
Now we can see that the third line can be simplified, in English, to “append
the HTML line break tag and ‘1’ to the #response
HTML element.” Then the
fourth line, in English, is “assign to the variable i
the result of 1 + 1.”
At the end of the first time through the loop, then, i
is now 2, not 1. Now
we can see it go back to the beginning of the loop. First, truth test: is 2 <
4
true? Yes. Next, append a line break and “2.” Next, reset i
to be equal
to 2 + 1, or 3. Once back through the loop… Now reset i
to be equal to 3 +
1, or 4 and…
Break. Because 4 < 4
is not true, the loop stops executing. More
colloquially, we break out of the loop. And that’s why your webpage should
read:
This is the #response div.
1
2
3
What are some changes we could make if we wanted it to go through the loop
four times? Two should be immediately obvious, and both involve changing the
truth test. We can change it either to i < 5
or i <= 4
. Remember, the <=
operator is the same as ≤, or less-than-or-equal-to.
It’s important to understand why this looping works the way it does, so it’s useful to loop over (as it were) this section until it’s clear.
For loops
For loops are just like while loops, except the truth test is replaced by a three part expression relating to a control variable. The three parts are:
- Initialization. What is the initial state of the control variable before the loop begins?
- Condition. What is the truth test that the control variable has to pass?
- Afterthought. What is the change made to the control variable each time through the loop?
If we look back at our while loop and consider i
to be the control variable,
we can see that a for loop is just a fancier version of a while loop. After
all, i = 1;
sets the initial state of the control variable before the
loop begins. Next, i < 4
is the condition that the control variable has to
pass in order for the loop to continue. Finally, i = i + 1;
is the afterthought,
or the change the control variable undergoes each time through the loop. In
other words, you can collapse a five-line program into just three:
for (let i = 1; i < 4; i = i + 1 ) {
$("#response").append("<br />" + i);
}
Note where the semicolons are placed, and also note that the two initialization lines
let i;
i = 1;
are collapsed into one statement, let i = 1;
. This works fine even outside
the while loop, but it’s tidier to define your variables and assign them
separately.
In addition to being terser, this syntax limits the control variable (i
) to
the loop itself, instead of defining it outside of the loop, like in a while
loop.
Loops are tricky, but they’re vital to understanding how programming works. Try out the exercises to see how well you understand them.
Exercises
(These are all to be written and tested using your project and the web browser.)
- Write a program so that when you reload your page, it asks for a number and prints all the numbers from 1 to it, including it.
-
Building on that program, create it so that instead of printing the number, it prints something like:
This is the #response div.
1 is odd.
2 is even.
3 is odd. - Building on the previous program, have it print the same, except without that ugly “This is the #response div.” line.
- Write down what seem to be common mistakes you are making. Are you forgetting to add some aspect of the JavaScript syntax?
Footnotes
-
Yes, you are now writing HTML without learning how to do it. The key grammar of the markup is clear from this example, though. HTML is made up of nested tags that look like this, for example:
<h1>
to open and</h1>
to close. Some tags, like the<meta>
and<!doctype>
tags don’t need to be closed, but most do. ↩ -
To give a sense of jQuery’s pithiness, the same line in vanilla JavaScript would be:
document.getElementById("response").innerHTML = "scripts.js has loaded!";
To my eyes, this is unnecessarily verbose. ↩