Apress Programming
Apress Programming
for Absolute
Beginners
Using the JavaScript Programming
Language
—
Jonathan Bartlett
Programming for
Absolute Beginners
Using the JavaScript
Programming Language
Jonathan Bartlett
Programming for Absolute Beginners: Using the JavaScript Programming Language
Jonathan Bartlett
Tulsa, OK, USA
—Linus Torvalds
Table of Contents
About the Author����������������������������������������������������������������������������������������������������� xi
Acknowledgments���������������������������������������������������������������������������������������������������xv
Chapter 1: Introduction�������������������������������������������������������������������������������������������� 1
1.1 What You Will Learn����������������������������������������������������������������������������������������������������������������� 1
1.2 How to Use This Book������������������������������������������������������������������������������������������������������������� 3
1.3 For Younger Programmers������������������������������������������������������������������������������������������������������ 4
v
Table of Contents
vii
Table of Contents
Chapter 11: Grouping Values Together with Objects and Arrays�������������������������� 145
11.1 A Basic Introduction to Objects����������������������������������������������������������������������������������������� 146
11.2 Simplifying Object Creation����������������������������������������������������������������������������������������������� 149
11.3 Storing Sequences of Values Using Arrays����������������������������������������������������������������������� 150
11.4 Using Arrays in Programs�������������������������������������������������������������������������������������������������� 151
11.5 Mixing Objects and Arrays������������������������������������������������������������������������������������������������ 154
11.6 Object Methods����������������������������������������������������������������������������������������������������������������� 156
11.6.1 Review���������������������������������������������������������������������������������������������������������������������� 159
11.6.2 Apply What You Have Learned���������������������������������������������������������������������������������� 160
viii
Table of Contents
ix
Table of Contents
Index��������������������������������������������������������������������������������������������������������������������� 323
x
About the Author
Jonathan Bartlett is a software developer, researcher, and
writer. His first book, Programming from the Ground Up, has
been required reading in computer science programs from
DeVry to Princeton. He has been the sole or lead author for
eight books on topics ranging from computer programming
to calculus. He is a senior software developer for McElroy
Manufacturing, spearheading projects in web, mobile, and
embedded software. He is now the author of several Apress
books including Electronics for Beginners and more.
xi
About the Technical Reviewer
Germán González-Morris is a polyglot software architect/engineer with more than 20
years in the field, with knowledge in Java(EE), Spring, Haskell, C, Python, and JavaScript,
among others. He works with web-distributed applications. Germán loves math
puzzles (including reading Knuth) and swimming. He has tech-reviewed several books,
including an application container book (Weblogic), as well as titles covering various
programming languages (Haskell, Typescript, WebAssembly, Math for coders, and
regexp). You can find more details at his blog site (https://devwebcl.blogspot.com/)
or Twitter account (@devwebcl).
xiii
Acknowledgments
I want to take a moment and thank everyone who helped me write this book. First, I want
to thank those who read and appreciated my first programming book, Programming
from the Ground Up. The encouragement I received from that book has given me the
encouragement to continue writing and educating throughout the years.
Next, I want to thank my homeschool summer co-op class for being guinea pigs
for this material. Your questions, your successes, and your difficulties all informed the
writing of this book. You were both my motivation to write in the first place and the first
proving ground for the material.
I would also like to thank my family, my friends, and my church, all of whom are
essential parts of my life. Thanks especially to my wife who puts up with me when I am
too focused on my writing to notice what the kids have been up to or to put a stop to
whatever trouble they have found themselves in!
xv
CHAPTER 1
Introduction
The modern world is filled with computers. Computers run our phones, our cars, and
even our refrigerators. Computers manage our businesses, our calendars, and our social
lives. With the world relying on computers for so many functions, it is important to know
how these devices work. Even if you never need to program a computer yourself, chances
are that, at some point in your life, you will be involved with software development.
You may be an accountant who needs to tell a computer programmer how you want
your purchasing system set up. You may be an engineer who needs to describe your
engineering process so that a programmer can automate it. In all such tasks as these, it
is important to know something about how computers are programmed, even if you are
not personally writing the software.
1
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_1
Chapter 1 Introduction
hired people for my development team who already knew the programming language
that my team uses. If someone learns one programming language and practices until
they are good at it, then the effort to learn a new language is fairly minimal.
You may wonder why, if the languages are so similar, there are so many
programming languages to choose from. The fact is, when engineering anything, trade-
offs have to be made. Sometimes in order to make one type of task easier, another type
of task has to be made harder. In my kitchen I have both a mixer and a blender. Both of
them operate on the same basic principles—you put food into the main container area,
an electric motor turns, and some attachment combines the food together. While these
tasks are very similar and operate on the same principles, there are many types of food
in the world and many ways that they need to be mixed, such that the mixer works better
for some tasks and the blender for others. Similarly, with programming languages, some
of them are better suited to different tasks. Also, the choice of programming language
is dependent on the programmer. Just as different types of cars suit the preferences and
tendencies of different types of drivers, so do different programming languages suit the
preferences and tendencies of different types of programmers. Because of these reasons,
there are numerous programming languages available for nearly any task you might
want to perform.
The programming language covered in this book is called JavaScript. I like to teach
JavaScript as a first language for several reasons. First of all, JavaScript was developed
to be a first language. One of the goals of the language was to make it easy for new
programmers to get started quickly. Even though JavaScript was designed to make
programming easier for new programmers, it is not any less powerful as a language.
Second, JavaScript has become the de facto programming language for website
interfaces. If you use a website that does anything besides link to other web pages,
JavaScript is probably involved. Therefore, learning JavaScript will have immediate
practical benefits in learning how the Web operates. Third, the tools for programming
JavaScript are available on every computer. You don’t need to download any special tools
to program JavaScript. If you have a computer with a web browser, you can program
JavaScript! Finally, JavaScript is very similar to other popular programming languages
such as C#, Java, and Swift. Therefore, knowing JavaScript will not only be immediately
beneficial for programming websites, it is also a language that makes it easy to transition
to other popular systems.
This book is for the first-time programmer. No prior programming experience is
assumed. This book does assume that you have a basic understanding of how to use your
computer and browse the Internet. That is all that you need!
2
Chapter 1 Introduction
You will learn not only the basics of computer programming but also a more general
knowledge of how computers and data work. You will learn where computers came
from, how they work, how computers work with data, how data is transmitted, and how
web pages work. This book will not go in-depth in all of these subjects, but it will give
you a basic working framework that will help you better understand ideas that you may
encounter elsewhere.
When discussing smaller pieces of code within a paragraph, code that is under
discussion will look like this.
Now, there are many different types of computers, each with different operating
systems and software loaded on them, with each of those having different versions.
There are also numerous different web browsers, each with different features available
and slightly different ways of working. This book attempts to walk you through setting
everything up on each operating system. If there is anything in this book that depends
on the specific operating system or browser that you are using, Appendix B has the steps
for several different systems, including Windows and Mac operating systems. This book
will refer you to the appropriate section of the Appendix when needed. Though this
book works with any modern web browser (basically anything released after 2008), I
recommend that you use Google Chrome. As of the time of this writing, Google Chrome
is the easiest browser to work with as a programmer. That being said, you should be just
fine with any web browser, including Brave, Firefox, Safari, Chrome, Opera, or Edge.
3
Chapter 1 Introduction
This book contains several practice questions and practice activities. The goal of
these questions and activities is to provide you with a hands-on way of understanding
the material. By doing the questions and activities, the text will become much more
meaningful and understandable. More importantly, they might show you the places
where you did not fully understand the text. Many people have a tendency to skip over
things if they don’t understand them well. Practice questions and activities give you a
chance to slow down and make sure you know which parts you understood and which
parts you need to read again and spend time thinking about. Practice questions build
on each other, so by doing them all in the order given, you can see exactly where you are
having problems.
At the end of every chapter is a review section which covers the most important
concepts of each chapter. After that is a section to help you practice applying your
knowledge to problems. These questions require you to further engage your brain and
really think about what you learned in that chapter and what it means.
Appendix A contains an extended glossary of terms used in this book, plus others
you are likely to encounter when reading about programming. This chapter will help you
find your bearings as you read and talk with other people about programming. I would
suggest that, concurrent with your readings, you also take the time to look through the
glossary for words that you may have heard but did not understand at the time.
Also, if you run into problems when writing code, Section B.6 has several suggestions
for getting you back on the right track.
4
PART I
A Short History
of Computers
The history of computers is weird and wonderful. What started as an abstract
philosophical quest ended up setting the course for society for over a century and
continues to be one of the most profound parts of modern life. The goal of this chapter is
to trace an outline of where computing started, where it has been, and where it is now.
7
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_2
Chapter 2 A Short History of Computers
to being near streams but could now go anywhere, since the power could be generated
from fire and stored water. Eventually this even allowed the creation of trains, since the
power could move with the vehicle.
The other invention of the industrial revolution was interchangeable parts.
This allowed a standardization and maintenance of equipment that was previously
unattainable. Instead of having each part be a unique piece, the parts became
standardized which allowed for the machines to become more specialized. It is one
of the more curious paradoxes of technology that as the pieces of technology become
less unique, the more advanced and unique the systems created from those parts can
become. Standardization allows for users of technology to stop having to think about all
of the low-level decisions and focus on the larger, more meaningful decisions. This also
allows for better communication about systems, because the parts can be more readily
described. If I can give you a schematic that lists premade parts, it is much easier to
design and communicate that design than if I also had to describe how each individual
part was supposed to be made.
So the introduction of available powered machinery and standardized parts in the
industrial revolution led to an explosion of specialized machines. We then had machines
to perform any number of tasks that a person could want to do. The next step was the
introduction of machines which were directed not by people directly controlling the
machine but by coded instructions. The earliest of these machines was the Jacquard
Loom, which used punched cards to signify a pattern woven into a fabric. The cards had
punched holes to signify to the machine the raising or lowering of the particular thread
causing it to be visible or hidden in the pattern. Thus, the loom could be programmed
to make a pattern by specifying at each point whether each thread should be raised or
lowered.
Later inventions applied this concept to mathematics. Calculating machines had
been around for a long time, with Blaise Pascal’s mechanical calculator having been
invented in the mid-1600s. However, this required the power of physical manipulation
to actually accomplish the addition. Most mathematical tasks are not single-step like
addition but require a process of several steps, sometimes repeating steps, before finding
an answer. Charles Babbage invented a more advanced machine to perform navigational
calculations. In this machine, the user entered the input, and then the machine used
that input to run a series of steps which eventually yielded results. Babbage eventually
designed a machine that could take a list of arbitrary instructions much like a modern
computer, but he was never able to build that design.
8
Chapter 2 A Short History of Computers
Once humans had the ability to power a machine, create a machine that operated
on external instructions, and use those instructions to perform mathematical functions,
they had all of the pieces in place to create a computer. However, the revolution that
brought about computing took place not from an invention, but from a problem in
philosophy.
9
Chapter 2 A Short History of Computers
1
If you want to dive deeper into this subject, you can see my article in MindMatters, “Why I Doubt
That AI Can Match the Human Mind,” available at https://bit.ly/3FOtOsS. You may also want
to check out my YouTube video, “How to Build an Artificial Intelligence Using the Doctrine of
Man,” available at https://youtu.be/FzXW7p3AG1Y.
10
Chapter 2 A Short History of Computers
and for the data that the program generates and operates on. This makes the computers
much easier to program and use, which led to the ability to sell computers commercially.
The first commercially available computer to implement this idea was the Manchester
Mark 1. The first mass-produced computer was the UNIVAC I, followed shortly after by
IBM’s 650. These computers were still massive in size but contained less memory storage
space than a single graphic on a modern computer. The UNIVAC I was the first computer
to have an external tape storage, and external disk storage (similar to modern hard
drives) followed soon after.
The next move for computer hardware was toward miniaturization. The original
computers used large devices called vacuum tubes to perform data processing (see
Figure 2-1, left column). These vacuum tubes would allow or not allow current to flow
based on whether other wires had current flowing through them or not. Combinations of
many of these tubes could allow for data to be stored as current flow, for mathematical
operations to be performed on such data, and for the data to be moved around.
After the vacuum tube came the invention of the transistor (see Figure 2-1, middle
column). Transistors generally have three wires, where the middle wire controls whether
the electricity can flow between the other two wires. As with vacuum tubes, transistors
can be wired together to create digital computer memory, digital computer logic
operations, and digital information pathways. Transistors, while they performed the
same basic functions as the vacuum tube, were able to do so in a much smaller package
and operating on a lot less power. Transistors allowed much smaller devices to be built
which also required almost 1,000 times less power. The Metrovick 950, released in 1956,
was the first commercial computer that operated on this principle.
Miniaturization continued with the advent of integrated circuits or what are often
called microchips or just chips (see Figure 2-1, right column). An integrated circuit
basically allows for miniaturized transistors to be stored on a small, single plate of
silicon. When integrated circuits were first introduced, they only had a few transistors.
Today, integrated circuits come in a variety of sizes, and the ones used for desktop
computing can hold billions of transistor equivalents on a 2-inch square chip. Integrated
circuits basically brought computers as we know them into the world. However, when
they were first introduced, they were primarily used by very large businesses.
In the 1960s, Douglas Engelbart led a research team to look at the future of
computing. In 1968, Engelbart presented what has been termed “the mother of all
demos,” which predicted and demonstrated nearly all aspects of modern personal
computing, including graphical interfaces, networking, email, video conferencing,
11
Chapter 2 A Short History of Computers
collaborative document editing, and the Web. This served as an inspiration for a number
of companies to start pushing to make this vision of computing a reality. Engelbart had
accomplished it in a lab, but others were needed to make it a commercial reality.
12
Chapter 2 A Short History of Computers
13
Chapter 2 A Short History of Computers
The 1990s witnessed the rise of Internet Service Providers, or ISPs, which provided
a way for computer users to use the modems that they used to use for bulletin-board
systems to connect their computers to the Internet. Instead of using a modem to connect
to a single computer, like they did with bulletin-board systems, the ISP allowed a user to
use their modem to connect to a whole network. This began the mass public adoption of
the Internet by both individuals and organizations of all stripes.
In the early days of the Internet, the speed of the network was very slow, and
only text could be transmitted quickly. Eventually, modems were replaced with more
advanced (and faster) ways of connecting to the Internet, such as DSL, cable, and fiber.
This allowed more and more complex content to be transmitted over the Internet. Also,
because these technologies do not tie up a phone line, they can be used continuously,
rather than intermittently. In addition, wireless technologies, such as WiFi and
cellular-based networking, allowed users to connect to the Internet without being tied
down by cables. These developments together led to the near-ubiquitous availability of
the Internet that we have today.
So, today, nearly all computer software is built with the network in mind. In fact,
much of the software that people use on a daily basis operates not on an individual
computer, but over a network. This allows for users to access software programs no
matter where they are or what computer they are using. It has also changed software
development so that the focus of computer software is no longer on individuals and
individual tasks but on organizing groups of people.
2.4.1 Review
In this chapter, we covered the basic history of computers. We have learned the
following:
• The isolated networks around the world were eventually unified into
a single Internet-work, known as the Internet.
15
Chapter 2 A Short History of Computers
16
CHAPTER 3
How Computers
Communicate
Before we start our study of computer programming, we are going to begin by studying
the way that computers communicate. The Internet is basically a giant communication
system. Communication systems operate using protocols. A protocol is a predefined
sequence of steps used to ensure proper communication.
We actually use protocols every day. Think about what happens when you answer
the phone. What do you say and why do you say it? Think about what happens when
you answer the phone (see Figure 3-1). This signals to the person calling us that we
have picked up the phone and we are ready to start talking. If we didn’t say “hello,” the
person might think that we accidentally accepted the call without knowing it or that we
are not quite ready to talk yet. Then, at the end of the call, we usually say something like,
“Thanks for calling! Goodbye!” This signals to the other person that we are done with the
conversation. If we didn’t tell them goodbye, they might think that we are still on the line
and continue talking. If they heard silence, they may presume that either we were not
speaking because we were upset or that there was a technical problem. Therefore, we
end our conversations with a “goodbye” to let the person we are talking to know that the
conversation is over.
This is the essence of a protocol. A communication protocol is a sequence of steps or
possible steps that enable two parties to communicate or interact and know the status of
the communication or interaction. Because computers cannot think or feel, computers
rely on very rigid and exact protocols to allow them to communicate with each other. In
fact, computers use hundreds of different protocols to communicate different types of
data in different ways. Most of the time, there are actually multiple protocols happening
at once.
17
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_3
Chapter 3 How Computers Communicate
Think about writing a letter. When you write a letter, there is a basic protocol that
governs the form of a letter—at minimum it should have a date, a greeting, and a closing.
However, if you decide to mail the letter, you have to send it through the mail service,
which has its own protocol. To send the letter through the mail, you need to take the
letter, fold it up, and put it in an envelope. What you write on the envelope is governed
by another protocol designed by the US Postal Service. Their protocol requires a return
address on the top left corner of the envelope, a destination address in the middle of the
envelope, and a stamp in the top right corner. Now you have two protocols happening
simultaneously—the letter-writing protocol and the envelope-addressing protocol.
These protocols are layered, which means that one of the protocols runs fully inside
of the other protocol. In computer jargon, we would say that the envelope protocol
encapsulates the letter protocol. The envelope protocol takes the results of the letter
protocol, packages it up, and puts its own protocol on top.
18
Chapter 3 How Computers Communicate
19
Chapter 3 How Computers Communicate
4. Now that we can move data across the Internet, there is another
issue. Other networks might not be as reliable as we want them to
be. Since we have no control over how reliable the other networks
are, we must adopt a protocol for making sure all of the data
arrives at the other side of the network safely and allows us to
retransmit any missing data that did not make it to the other side.
This layer is called the transport layer.
20
Chapter 3 How Computers Communicate
As you can see, there is a lot going on when you send a message from one computer
to another through the Internet! Thankfully, since this is built in layers, we rarely have to
think about all of the things that are going on at the different layers. For instance, when
you mail a letter to a friend, you never have to think about the different mail sorting
facilities, postal routes, or delivery times of the post office. That is a system that is already
in place, and you must simply drop your letter in the mailbox and let the system do the
rest. That is the same with communication on the Internet. However, it is good to know
what is happening behind the scenes, both so you can better understand the capabilities
of the system you are using and so you can better identify issues when something
goes wrong!
Computers haven’t always been connected through the Internet, and the OSI Model
was developed when the Internet was not the primary means of communication. In fact,
at the time, nearly all communication was on private networks. Since its development,
certain technologies have become fairly standard in each layer. Figure 3-2 shows
common technologies used at each layer.
For the physical layer and data link layer, the two primary technologies are Ethernet
for wired connections and Wi-Fi for wireless connections. In addition, your connection
to the Internet, whether it is through cable, DSL, or fiber, also uses its own physical
and data link layers. The network layer is handled by the Internet Protocol, usually
abbreviated as IP. The number that identifies each computer on the Internet is known
21
Chapter 3 How Computers Communicate
as the computer’s IP address. On the Internet, the transport and session layers are
usually combined and handled through a protocol called the Transmission Control
Protocol, abbreviated as TCP. Because TCP and IP are almost always seen together, they
are often collectively labeled as TCP/IP. The only common presentation-layer protocol
is the Transport Layer Security protocol, usually abbreviated as TLS or SSL (based
on its original name, the Secure Sockets Layer). TLS handles the job of encrypting and
decrypting data on a secure connection, to prevent other people from being able to listen
in on your communication.
Thankfully, however, we rarely need to know much about these layers. In fact,
this is one of the main reasons such layers were invented—so that all an application
programmer really needs to interact with is the application layer. It is still good to know
that these other layers exist, as occasionally you might interact with them. In addition,
knowing the basics of how the network works is part of being a programmer.
The layer that most computer programmers deal with directly is the application
layer. There are several application-layer protocols that operate on the Internet. The
Internet is best known for HTTP, which is the protocol used to access websites. Second
to HTTP is probably SMTP, which is the protocol used to send email. POP and IMAP
are two protocols often used to receive emails if you use a separate email program. These
protocols make up a large majority of people’s use of the Internet.
22
Chapter 3 How Computers Communicate
Each URL has three main parts—the application-layer protocol, the hostname (the
server’s name or IP address), and the document path. Optionally, there is also a fourth
and fifth part, the query string and the anchor, which provide additional information
to the server and/or the JavaScript on the page itself. In a URL, the protocol is everything
up until the colon. In this case, it is “https,” which is the normal protocol used on the
Internet for encrypted connections. If the connection is an unencrypted connection, the
protocol would just be “http.” The two slashes after the protocol indicate that the next
piece of the URL is the hostname. In this case, the hostname is www.bplearning.net.
We will discuss hostnames in more depth in Section 3.4. The slash after the hostname
is the beginning of the path. The path includes the starting slash and is essentially the
rest of the URL. Sometimes the path is extremely short. For instance, when you first
go to a website, the path is usually just /. It can also be very long, like /orders/123/
products/5. The way to think about a path is that each piece of the path is like a folder
on your computer, and the path is the list of folders someone has to go through to find
a document. That isn’t exactly what is happening on the server, but it is a helpful way of
thinking about it.
For an example, open up your browser. Find the location bar in your browser. (For
more information on finding the location bar in your browser, see Section B.1.) Put
https://www.bplearning.net/example/ into the location bar and press the enter key.
This will bring up an example website that I built for this book. Depending on your
browser, it might show you the whole URL, or it might remove the protocol from the URL
to make it easier to read. Some browsers will also remove the path unless you actually
click in to the location bar itself.
Now, click on the link titled “About.” Once the page finishes loading, take another
look at your browser’s location bar. The location bar should now read https://www.
bplearning.net/example/about.html. That URL is used to find the server and tell
the server what document it should give you and the protocol for the communication
channel.
23
Chapter 3 How Computers Communicate
Now we will look at how the browser actually retrieves the document. Data
transmission on the Internet using HTTP is not quite as mysterious as it may seem.
The main steps are as follows:
Once the connection with the server is established, here is what the protocol looks
like to request the “about” page:
The first line, called the request line, does most of the work. It has three components.
The first component is called the HTTP verb. This tells the server what action you are
trying to do. You are retrieving the document, so you use the GET verb. Other verbs
include DELETE for remotely destroying documents and POST for sending data to a
document on the server. The next component is the path, which tells the server how to
find the document. The last component is the protocol version—you are using HTTP
version 1.1.1
The next few lines are called the request headers. They are a list of options that you
send to the server to clarify in more detail what you want and how you want it delivered.
The first request header line that we send tells the server what hostname you are looking
for. This may seem redundant, since we already connected to the server that we want.
However, modern web servers are actually built to serve requests for any number of
hostnames which may be sharing the same server. Therefore, even though you are
connected to the server for www.bplearning.net, you still have to tell it what site you
were really looking for. The next header line is optional, but it tells the server to close
1
Note that, starting with HTTP protocol version 2, the protocol will no longer be based on textual
commands, so you won’t be able to use HTTP 2 via the keyboard alone. However, servers will
likely maintain backward compatibility with HTTP/1.1 indefinitely.
24
Chapter 3 How Computers Communicate
the connection after it gives you the document. Otherwise, it will sit and wait for you to
request something else. Then, to signal that we are at the end of our request headers,
we send a blank line. There is also an optional request message (called the request
body) that we can send at this point, but that is beyond the scope of our discussion. The
requests we will be discussing in this chapter will not have a request body.
When the server receives the blank line, it knows that you are done asking for your
document, and it attempts to process your request. It then responds with something that
looks like this:
HTTP/1.1 200 OK
...Possibly other data here...
Server: Apache
Content-Type: text/html; charset=UTF-8
...Possibly more data here...
The response is very similar in format to the request. The first line is the response
line. It lists the protocol version that the server is responding with, followed by a status
code and status message. 200 is the status code that means everything went just fine and
there is a document coming. Other common status codes include 404 which means that
the document could not be found, 500 which means that the server ran into an error, 301
and 302 which mean that the document has moved locations, and 400 which means that
the request did not follow the proper protocol or sent bad data. After the response line
is a series of response headers. These communicate additional information about the
server and the response. The headers shown here are just an example—most servers give
back several more headers as well and usually in no particular order. The two headers
shown tell us the type of document we have retrieved (in this case, an HTML file, which
is what Content-Type: text/html means) and the name of the server software that the
server is running (Apache in this case). The server then sends a blank line telling us that
it is done sending the headers, and the rest of the communication will be the document
we asked for. The document we get back is an HTML file. It may look strange, but that
is exactly what the browser receives from the server. It includes all of the data that the
browser needs to display as well as the instructions for how to display it on the screen
and how you can interact with it.
25
Chapter 3 How Computers Communicate
telnet www.bplearning.net 80
You are now talking directly with the web server yourself! Now you just need to
follow the HTTP protocol to get what you need. Type in the request that we mentioned
earlier (note that the request ends with a blank line):
The server will then respond with its response line, response headers, and response
message as outlined above. However, it won’t be the page we requested. It will, instead,
be a redirect response. The reason for this is that the website only allows secure requests,
and HTTP by itself is unencrypted. Therefore, we have to communicate using HTTPS
(HTTP over a secure/encrypted connection) rather than just HTTP.
You may be wondering what the 80 is doing in the original telnet command.
That is the port that the HTTP server listens on by default. Servers use “port numbers”
to know what service is being requested, as each service listens on a different port
number. Port 80 is the standard port number used for HTTP communication. For our
26
Chapter 3 How Computers Communicate
HTTPS communication, we will be connecting to port 443, which is the standard port
for HTTPS.2
The command to communicate via HTTPS is openssl, which does essentially the
same thing as telnet but establishes a secure connection first (openssl actually does a
lot more, but we won’t concern ourselves with its other functionality). Since the standard
port for HTTPS is 443, not 80, we will have to connect using that port. In order to connect
using openssl, we have to issue the following command (the command is lengthier
because openssl has so many options and other capabilities):
From here, you can issue the same request as above. Since encryption happens
on the presentation layer, no changes are needed to the protocol that we type, which
happens entirely at the application layer. The openssl command handles all of the
presentation-layer encryption for us.
The response this time is the full document you requested (as well as the HTTP
headers).3
You have now communicated directly with a server using the HTTP protocol. You
have spoken your first bit of computer-ese!
2
The standard port numbers are essentially arbitrarily chosen. The Internet Assigned Numbers
Authority (IANA) is responsible for assigning which services are supposed to listen on which
port. Port assignments for services essentially depend on when services were developed and
which ports were unassigned when the service was standardized. Technically, there is nothing
preventing a server from listening on a wrong port or running a different protocol on a standard
port, but then the browser won’t know how to access it.
3
If you already know HTML, then, depending on the response length, you might notice that there
are a few extra letters and numbers in the response that aren’t in the HTML file itself. This is due
to the “transfer encoding,” which sometimes sends the HTML in chunks. Those numbers and
letters tell the browser how much data is coming in the next “chunk.” However, since we haven’t
covered HTML yet, you probably didn’t notice the extra numbers and letters in the response. In
any case, for our purposes, they can be ignored.
27
Chapter 3 How Computers Communicate
We talked in Section 3.1 about the different protocol layers in the Internet. Layer 3
is the network layer, and, on the Internet, the network layer is handled by the Internet
Protocol (IP). The Internet Protocol mandates that each computer on the Internet
is identified by a series of numbers, known as the computer’s IP address. However,
we don’t normally refer to computers by that series of numbers for two reasons. The
first reason is that humans aren’t good at remembering numbers. It’s much easier to
remember google.com than it is to remember 64.233.160.138. The second reason
is that it is good to separate out physical issues from logical issues. In other words, the
IP address tells the network what physical location on the Internet you want to go to.
However, the user doesn’t care where that is. The user just wants to go to Google’s
website. Therefore, by creating a name for Google’s website (i.e., google.com), the user
can access the site even if its physical location on the network changes. The IP address
is similar to a phone number, and the hostname is like the name of the person you want
to reach.
However, when you want to connect to a server for a website, the computer must
know the destination IP address to make the connection. How does the computer know
what the IP address is for the website you want to visit?
The computer finds the destination IP address through the Domain Name
System (DNS). DNS is a system that translates hostnames to IP addresses, kind of
like the way a phone book translates a person’s name into a phone number. However,
DNS is a distributed system, so, rather than just one big phone book, there are
millions of them organized into a hierarchy. Each server (i.e., “phone book”) in this
system is called a nameserver. So, when you tell your browser you want to go to www.
bplearning.net/example/about.html, before it makes a connection to the server,
it must first figure out where www.bplearning.net is located. In order to do that, it
breaks the hostname down into pieces, separated by a dot. In our case, there are
three pieces—www, bplearning, and net. The browser starts with the rightmost piece,
called the top-level domain name (TLD). Each browser is preprogrammed with a set
of “root” nameservers. The browser begins by asking the root nameservers if they
know who maintains the DNS records (i.e., who handles the phone book) for .net
domains. The root nameserver responds with the IP address of the nameserver or
nameservers that handle requests for those domains. Next, the browser goes to the
.net nameserver and asks it who maintains the DNS records for the bplearning.net
domain. The .net nameserver will point to yet another nameserver who handles the
bplearning.net domain. Finally, the browser will go to the bplearning.net nameserver
and ask it if it knows what the IP address of www.bplearning.net is. The bplearning.
28
Chapter 3 How Computers Communicate
net nameserver will respond with the IP address of www.bplearning.net, and with
that IP address, your computer will be able to establish a connection to the www.
bplearning.net server.
This usually happens in a fraction of a second, so we don’t notice that the computer
is doing all of this work behind-the-scenes. In addition, the computer usually skips the
steps that it has performed recently and just remembers what results it got back last time
so that it doesn’t have to do the same query over and over again.
3.4.1 Review
In this chapter we covered the basics of Internet communication. We have learned the
following:
• A URL is a piece of text that gives the browser all of the information it
needs to locate a document on the Internet.
• The path of the URL is sent to the server to identify the document
being requested.
29
Chapter 3 How Computers Communicate
4. Go to the command line and try to retrieve the web page for
JavaScript from Wikipedia directly using the HTTP protocol.
30
CHAPTER 4
How a Computer
Looks at Data
Chapter 3 covered the basics of how computers transmit data to each other over the
Internet. This chapter expands on that, covering how documents are stored within the
computer. Much of the information in this chapter, like the last one, is more background
information than practical knowledge. The JavaScript programming language automates
a lot of the data handling for you, so you don’t have to worry about it. Nonetheless, it is
important to know what the computer is doing for you!
We think of computers as systems which are capable of anything, but in reality
computers are very limited. In many areas of engineering, engineers achieve the most
powerful results by limiting the possibilities, which makes the remaining available
possibilities more potent. Engines are made by taking the energy from combustion
reactions and channeling them in a specified direction to operate the engines. Instead of
letting the energy go in every direction (which is what it normally does), it is only allowed
to go in specific directions. The driver of the car can go anywhere he or she wants to, but
only because the combustion within the engine is directed to a very limited number of
directions. Computers are powerful precisely because they are similarly limited.
Computers, at their core, perform two functions—they process numbers and they
transmit numbers. This may seem counterintuitive. After all, when you type on your
keyboard, doesn’t it produce letters on the screen? Doesn’t your computer do graphics
and sound? In reality, all of these things are controlled by numbers. The color of each
pixel on your screen is a number. Each letter you type has a corresponding number.
Each sound is a long sequence of numbers. The computer may look like it is doing
lots of different things, but it is really doing only two things—processing numbers and
transmitting numbers.
31
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_4
Chapter 4 How a Computer Looks at Data
The first part of this chapter will cover how data is stored on a computer using
numbers. The second part of this chapter will cover how those numbers can be arranged
into a file format which can be read by software applications like web browsers.
32
Chapter 4 How a Computer Looks at Data
Figure 4-1 lists the numbers zero through eleven in decimal and in binary.
If you carry this out, you will find that the number 255 is the maximum number
that you can get with 8 bits. It looks like 11111111 in binary. In short, the reason why a
computer byte stores numbers between 0 and 255 is because a byte is made up of 8 bits.
It is important to note that the numbers in the left column and right column are
the same numbers, just represented differently. The reason we use decimal numbers is
probably due to the fact that our culture started counting with its fingers. A few cultures,
such as the Yuki, started counting using the spaces between their fingers and therefore
only have eight digits in their system. The numbers in each of these cases are not
different—only the way they are displayed!
Two other systems that are regularly encountered in computer programming are
the octal system and the hexadecimal system. The octal system uses only the digits 0–7,
but the hexadecimal system actually adds digits to our current ones. Hexadecimal uses
letters to add additional digits. So, in hexadecimal, the letters A–F represent the decimal
numbers 10–15, and 10 in hexadecimal is the same as the number 16 in decimal.
33
Chapter 4 How a Computer Looks at Data
Figure 4-2 shows a combined list of the numbers 0–16 in decimal, binary, octal, and
hexadecimal:
The reason why octal and hexadecimal are often used in computing is that a single
octal digit represents exactly 3 bits, and a single hexadecimal digit represents exactly
4 bits. Two hexadecimal numbers together represent 1 byte. Therefore, octal and
hexadecimal are essentially used as a shorthand for writing binary numbers. An example
of this is in screen colors. Each dot on your screen is represented by 3 bytes—1 byte for
the red component, 1 byte for the green component, and 1 byte for the blue component.
In many tools, these are all smashed together as a six-digit hexadecimal number.
For instance, red is represented by FF0000, green is represented by 00FF00, blue is
represented by 0000FF, a greenish blue would be 00FFFF, and a darker shade of greenish
blue would be 009999.
In any case, computer memory is a long sequence of millions or billions of bytes, one
after another. Each byte has an address, which is basically like a locker number, so you
can refer to specific memory locations on the computer. We won’t be accessing bytes by
their memory addresses ourselves, but that is how the computer works at the lowest level.
34
Chapter 4 How a Computer Looks at Data
Now, it might seem very limiting to only be able to deal with numbers that are
between 0 and 255. The reason this is not a problem is because this is only how the
machine works at the lowest level. Programming languages group several of these
bytes together to represent much larger numbers or other kinds of data altogether.
Representing numbers that have a decimal point is a harder problem, but it is usually
done by designating some number of bits to be the number without a decimal point and
some number of bits to be the location of the decimal point in the number. Even though
you won’t have to deal with these details in JavaScript, it is good to keep in mind that,
at the lowest level, everything you deal with is just a sequence of numbers between 0
and 255.
Going forward, we will assume that the computer can handle whatever size number
we throw at it. This isn’t entirely true, but it is true enough for our purposes.
PRACTICE QUESTIONS
• Since black is the absence of color, how do you think you would represent
black in the hexadecimal system discussed in this section?
• Height
• Weight
35
Chapter 4 How a Computer Looks at Data
Some of these values are actually numbers, like height and weight. We just have to
decide what units we are using. Let’s use inches for height and pounds for weight. Hair
color and eye color are not numbers, but computers only have numbers to work with.
So, what do we do? We choose numbers to represent the possible values. We might
say that, for hair color, black is 0, blonde is 1, brown is 2, red is 3, and white is 4. There
doesn’t have to be any reason that a color gets a particular value. The important thing is
to make sure that whatever number we assign, we consistently use that same number to
represent that hair color. Next, we can choose numbers to represent eye color. For eyes,
we can say blue is 0, green is 1, and hazel is 2. It doesn’t matter that our numbers overlap
with the same numbers we used for hair color, as long as we know which one we are
dealing with.
We can now represent a person with a sequence of four numbers—their height,
weight, hair color, and eye color. Using this system, I would be 72, 275, 2, 2. Someone
identical to me, but with blue eyes, would be 72, 275, 2, 0. Notice how important the
order of the numbers is. If we didn’t know what order the numbers were in, we wouldn’t
be able to understand the data. It isn’t that the numbers are in order of importance—
we could just as easily have arranged it as weight, eye color, height, hair color—the
important thing is that we know what order to expect the numbers and follow that
convention every time we use the data. Otherwise, we might wind up mistaking
someone’s weight for their height or their eye color for their hair color.
When you have a predefined set of data to describe something, it is called a data
format. It might not seem like a data format is that big of a deal. However, when
communicating with other programs, they may have their data in a different pattern than
you do with yours. Imagine another program which stored the same data but used feet
instead of inches for the height. Or, let’s say that it had five numbers for each person,
with the fifth being their age. In each of these cases, if you loaded data from this other
format, you would have to convert the data from the data format you are given to the
data format you need for your own program. This may include transforming certain
pieces of data (e.g., feet to inches), ignoring certain pieces of data (since our format
doesn’t include an age), calculating data (if one program needs an age or another
program sends the date of birth), or any other number of possibilities. These are called
data transformations and account for a very large portion of programming tasks.
36
Chapter 4 How a Computer Looks at Data
PRACTICE QUESTIONS
2. Write out in plain language what someone with the following numbers
looks like:
69, 150, 0, 1
4.3 Sequences in Data
The data format we explored in Section 4.2 is only helpful if we have a fixed number of
things to store. Because each piece of data is identified by its position in the sequence,
if we changed the number of items in the data, we would also change what they meant.
Let’s say you wanted to store the ages of a person’s children. The problem is that we
don’t know how many children a person might have. They might have none or 20. One
way to solve the problem is to have a count of the number of children first and then the
children’s ages. This way we would know when the children’s ages stopped. For instance,
we could modify our format to be height; weight; number of children; age of child 1, age
of child 2, etc.; hair color; and eye color. By storing the number of children before the list
of children, even though each record would have a slightly different length, we would
still know where each piece of data is in the record because we know how many children
we need to be looking for.
Let’s say that our friend Fred has three children, ages 12, 10, and 5. His record might
look like this: 70, 200, 3, 12, 10, 5, 1, 1. The number 3 tells you that the next three
records will be children’s ages. After that, you go on to the rest of the record.
Another way of storing repeated values is to use what is called a sentinel value. A
sentinel is a value that tells you that you are at the end of a list. Therefore, rather than
storing the number of children, we could decide that we are going to use a sentinel value.
Since no children have a negative age, we could use a -1 to indicate that we are at the
end of the list, rather than having a count. Under this scheme, Fred’s record would look
like this: 70, 200, 12, 10, 5, -1, 1, 1.
Such sequences of data are commonly referred to as arrays. An array is simply
a sequence of data that is packaged together into a single set. In this example, the
children’s ages are treated as an array.
37
Chapter 4 How a Computer Looks at Data
PRACTICE QUESTIONS
1. What would Fred’s record look like if he had six children, aged 21, 19, 14, 12,
10, and 5, using the format that counts his children?
2. What would that record look like using the format that has a sentinel value?
3. Why is it important that the sentinel value not be a possible data value?
38
Chapter 4 How a Computer Looks at Data
followed by the list of characters or as a list of characters with a sentinel value. In ASCII,
the decimal number 0 is a special character called the null character, which is used as
a sentinel for a list of characters. An array of characters is often referred to as a string,
and a string that is represented using a null for its sentinel value is often called a null-
terminated string.
Let’s go back to our person data format before we added the children. Let’s say we
wanted to store the name of the person to the record. The record would store the name,
height, weight, hair color, and eye color. We can use a null-terminated string for the
name. Therefore, my name, “Jon,” would be encoded as 74, 111, 110, 0. Then, my
whole record would be as follows:
You can tell where my name ends and the rest of the record begins by the sentinel.
Now, let’s add children, using -1 for the sentinel value. We’ll pretend I have two
children, Jim and Bob. In the next record, we will use the format name, height, weight,
hair color, eye color, name of child 1, age of child 1, … , -1. It looks like this:
PRACTICE QUESTIONS
• Look at the record above. Based on the format, what is Jim’s age?
• Create a new record for me if I had another child named Mary Ann, aged 6.
As you can see, in order to process data, computers have to be very exact about what
kind of data goes where, how long it is, and whether it repeats. In order for two programs
to communicate, or even for two functions within the same program to communicate,
they must both agree on the format of the data. Now, in modern programming languages
such as JavaScript, the representation is much nicer than a string of numbers. JavaScript,
for instance, allows you to say "Jim" instead of 74, 105, 109, 0, but underneath it
actually does the same thing. "Jim" is a string of characters. In most programming
languages, putting quotations around a string of characters indicates that those
characters should be treated as a string of text. Generally, if you see 234 in a program, it
means the number 234, but "234" means the string of characters 2, 3, 4 (which would be
represented by the numbers 50, 51, 52 in ASCII).
39
Chapter 4 How a Computer Looks at Data
40
Chapter 4 How a Computer Looks at Data
Notice, however, that there is a subtype, “html.” This indicates that text files
themselves can have formats. That is, we can organize a text file such that it is easy for
a computer to locate specific kinds of data. For instance, spreadsheets often use CSV
(comma-separated value) files. The CSV file format uses a comma to separate data that
go into different columns and a return character to separate data that go into different
rows. Figure 4-3 shows a sample CSV file with three columns and four rows.
Since a CSV is a text document, this whole file would be stored as a string of
characters. A spreadsheet, when loading the document, might convert columns 2
and 3 into numbers, but, on a disk, since it is a text document, it is stored as a string of
characters. The format says that when the spreadsheet loads the file, it should split the
row into columns based on where the commas occur and split the file into rows based
on where the line breaks are. So, because it is a text format, all of the details of the file
are easily viewable and understandable by people, since it is just a string of characters.
However, it is in fact a data format because the different pieces of the file have significant
meanings—in this case, the commas and the newline characters.
In Chapter 6 we will look at the HTML file format.
PRACTICE QUESTIONS
To see the difference between text files and binary files, open up different file types with your
text editor. For information on what a text editor is and how to use one, see Appendix B.3.
2. Open up a file on your computer with one of the following extensions: .jpg,
.jpeg, .png, .pdf, .mp3, .doc, .xls. If your computer is not showing you
the file extension, Section B.3 describes how to make them visible.
41
Chapter 4 How a Computer Looks at Data
3. Since you are using a text editor, it will attempt to treat each number in the file
as if it were a character. This is what makes all of the funny characters—your
text editor doesn’t know how to deal with the non-text characters.
4. Now open up a file on your computer with one of the following extensions:
.txt, .csv, .html, .rtf. If you don’t have any of these types of files, you
can easily create a .rtf file using any word processor. Just tell the word
processor to export your document in “Rich Text Format,” and it will produce an
appropriate file with an extension of .rtf.
5. Even if you don’t understand the file, it should at least be viewable—you should
recognize the characters that it is using.
6. Note that the extensions themselves don’t do anything—they are merely there
to help you know what is in the file, what program to use to open the file, and
what icon to display for the file. Your operating system keeps a list of default
programs to use for various file extensions. If you change a file extension of a
file, the computer will likely open up the wrong program for that file!
4.5.1 Review
In this chapter, we covered some of the details about how computers look at and process
data. We have learned the following:
• Lists of data are often stored by storing the length before the number
of data items or by using a sentinel value to indicate the end of a list.
42
Chapter 4 How a Computer Looks at Data
• A text file is a file format where the entire file is stored as one
long string.
43
Chapter 4 How a Computer Looks at Data
44
CHAPTER 5
45
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_5
Chapter 5 How Computers Work
The examples in this chapter may seem tedious. They are. Few people program
in machine language anymore because it is quite tedious. Don’t worry, though,
programming languages were invented specifically to remove the tediousness of
machine language. The point here is to introduce you to the way a machine thinks so
that you will better understand the exactness required and start thinking in the ways that
the computer needs you to think. In my entire programming career, I have never needed
to program in machine language. However, knowing how machine language works has
helped me immensely to align my imagination and thinking to better understand how to
make my programs work.
5.1 Parts of a Computer
You can conceptually break a computer into four main pieces:
• An input/output system
• A data bus which moves the data between these different parts
The computer’s CPU is where most of the data processing happens. The CPU itself is
divided into two components—the control unit and the arithmetic and logic unit (ALU).
The control unit manages the process of computing itself. The control unit maintains a
piece of data called the instruction pointer which holds the location in memory of the
next instruction to perform. The control unit looks at an instruction, determines what is
needed to process that instruction, and then manages all of the components needed to
make that instruction happen. This might include things like writing and fetching data to
and from the memory, reading and writing data to the input/output system, and telling
the arithmetic and logic unit to perform computations. The arithmetic and logic unit
performs basic calculations, such as add, subtract, multiply, and divide, directly. It also
performs logical comparisons, such as comparing if two values are equal or if one value
is greater than another. Although some processors have more basic calculation features
than others, all of them are computationally equivalent. Even if you only had a processor
that could add and subtract, you could write additional code that would use addition and
46
Chapter 5 How Computers Work
subtraction to be able to multiply and divide. A computer equipped with only minimal
instructions can perform any computation necessary—it just takes more work from the
programmer. The ALU can also contain temporary storage locations, called registers,
which are used to perform the computations and store the results.
The computer’s memory is where a computer stores data that is being actively used
for processing. The computer’s memory is not the same thing as its hard drive. The hard
drive is actually external to the computer and is connected through the input/output
system. The hard drive is where data can be permanently stored. Computer memory
is where data is stored while it is being used. To conceptualize the difference, if you
turn off your computer suddenly, the information stored in memory is wiped away. In
Chapter 4, we discussed how computer memory was laid out. It is divided into billions
of storage locations, where each location can hold a number between 0 and 255. The
locations themselves are numbered so that they can be identified and accessed easily.
The input/output system in a computer is tasked with communicating with the
outside world. The main computer itself is incapable of interacting with people.
Keyboard input, screen output, hard drives, network adapters, and all of the other things
that we think of when we interact with our computer are all actually on the “outside” of
the computer, connected through the input/output system. There are several standards
for input/output systems, the most common of which is the Universal Serial Bus (USB).
USB defines a standard way of connecting input/output devices to a computer. This
allows USB drives, USB cameras, USB keyboards, and a myriad of other devices to all
connect to your computer. Without the input/output system, computers would be
impossible to use, as there would be no way for us to give it data or programs or see the
output of computations.
The data bus handles moving data between each of these systems. It is an important,
but often overlooked, feature of computer systems. For instance, if you have a really
fast CPU and a lot of memory, neither of these do much good if the data bus is slow
in moving the memory to the CPU. Buses are connected together by hubs, which
direct traffic to and from each device. Many modern computer architectures have two
separate hubs. The fastest hub, which connects directly to the CPU, is often called the
northbridge. It connects the CPU to the memory and the graphics card. The other hub,
often called the southbridge, connects from the northbridge to the rest of the input/
output systems.
47
Chapter 5 How Computers Work
48
Chapter 5 How Computers Work
49
Chapter 5 How Computers Work
50
Chapter 5 How Computers Work
51
Chapter 5 How Computers Work
This simulation is easy to do in a class setting and was actually originally developed for use in
a class. To do this, you need to use markerboards or chalkboards rather than sheets of paper.
Appoint one student to be the Control Unit. This student is responsible for performing the steps
outlined above, but they cannot leave the control unit area or write on another student’s board.
Appoint another student to be the Data Bus. This student is responsible for transferring all
needed data to and from the Computer Memory. The Control Unit will direct which values the
Data Bus needs to fetch or store. The Data Bus only takes instructions from the Control Unit.
Appoint another student to handle the Arithmetic and Logic Unit sheet. They will perform any
computation requested by the Control Unit on its registers and can give to the Control Unit any
value that has been computed in its registers.
I have found that doing the computations interactively greatly increases the ability of students
to visualize what is happening inside the computer and makes them better programmers
long-term.
5.3.1 Setting Up the Simulation
To begin the simulation, the code and the data are both written into memory. Copy the
values from Figure 5-4 into your Computer Memory sheet.
Before you decide to quit programming altogether, let me remind you that the point
of this exercise is not that we would ever actually program this way but rather to give you
a glimpse into how the computer looks at processing. The very reason that computer
programming languages were invented was so that we would not have to deal with this
stuff on a daily basis. So, to allay your fears, Figure 5-3 shows what this would look like in
JavaScript.
You still may not understand what exactly this does or why it is written that way, but
hopefully it gives you hope that it will be more understandable than a bunch of numbers
written out.
Now, to run the program, you need to look at the steps in Figure 5-2. We will go
through them step-by-step so you know how to do it.
5.3.2 Running the Simulation
Now, let’s go through the program step-by-step to see what is happening. This will all
be done in pencil. Look at Figure 5-2. The first thing it says is to double-check that the
memory locations were copied over correctly. Do this now. Next, it says to write a 0 in the
box labeled Instruction Pointer. Do so now. Now we can proceed to the numbered steps.
Step 1 says to look at the instruction pointer. It should read 0.
Step 2 says to look at the memory location indicated by the Instruction Pointer. Since
ours says 0, we will look at memory location 0.
53
Chapter 5 How Computers Work
Step 3 says to copy the value at that memory location to the first line of the Control
Unit sheet under the heading Opcode. The value at memory location 0 is 22, so we will
write 22 in the first line of the Control Unit sheet in the Opcode column.
Step 4 says to copy the next value in memory to the column labeled Operand 1. The
next memory location is memory location 1, and it has the value 0. Therefore, we will
write the number 0 to the Operand 1 column. We then copy the next value in memory
(memory location 2) to the Operand 2 column. Memory location 2 has the value 62 in it,
so write the number 62 in the Operand 2 column. This is our first instruction: 22, 0, 62.
Step 5 says to add 3 to the value in the Instruction Pointer. The instruction pointer
currently has a 0 in it, so 3 + 0 is 3. Erase the 0 and write 3 in the box. This will allow
us to read the next instruction the next time we go through the steps. However, it is
important to do this now rather than at the end of the steps, as some instructions may
further modify this value.
Step 6 says to look up the value in the Opcode column in the list of opcodes in
Section 5.5. The opcode is 22, so go through the list of opcodes to find opcode 22. The
opcodes are not listed in numerical order, so you will need to look through all of them
until you find the right one. The opcode is “Load Memory.” Therefore, write “Load
Memory” in the column labeled Meaning.
Step 7 says to perform the steps listed in the opcode table for this opcode. You will
notice that the opcode table says that Operand 1 refers to a register and Operand 2 refers to
a memory location. Therefore, we will be working with register 0 and memory location 62.
The description says to load the value in the memory location specified by Operand 2 into
the register specified by Operand 1. Therefore, we will load the value in memory location 62
into register 0. Memory location 62 has the value 12 in it, so we will write 12 in register 0 on
the Arithmetic and Logic Unit sheet.
Step 8 says to go back to step 1 and repeat for the next instruction.
Now we are back to step 1. Therefore, we need to look at our Instruction Pointer
again. This time it is set to 3. Step 2 says to look at the memory location indicated by
the instruction pointer. It contains the number 21. Step 3 says to copy that number to
the next line on the Control Unit sheet under the Opcode column. Therefore, write the
number 21 into the Opcode column. Step 4 says to copy the next two memory locations
to the Opcode 1 and Opcode 2 columns. The next two memory locations have the
numbers 1 and 0 in them, so write 1 in the Opcode 1 column and 0 in the Opcode 2
column. The instruction we copied is 21, 1, 0.
Step 5 says to add 3 to the Instruction Pointer. Therefore, write 6 in the Instruction
Pointer box, erasing the previous value.
54
Chapter 5 How Computers Work
Step 6 says to look up the value that is written in the Opcode column in the list of
opcodes in Section 5.5 and write the name of the opcode in the Meaning column. The
meaning of the opcode is “Load Register.” Step 7 says to do what the description of the
opcode says to do. The description says to copy the value of the register specified in
Operand 2 into the register specified by Operand 1. Operand 1 is 1 and Operand 2 is 0.
Therefore, look at register 0. It currently contains the number 12. So write 12 into the box
for register 1.
This instruction has given us two copies of the same number—one in register 0
and one in register 1. This is good because multiplication by 2 is just adding the same
number twice. Therefore, what type of instruction do you think will come next? Look
through the list of instructions to see which one you think we will do next. Step 8 says to
repeat the process for the next instruction, so let’s do that now.
If you go through steps 1–4 again, you will have the next instruction copied over,
which is 133, 0, 1. Step 5 then tells us to add 3 to the Instruction Pointer, so write a
9 in the Instruction Pointer box. Step 6 says to look up the Opcode (133) in the list of
opcodes and write down its meaning. Write “Add” in the Meaning column. Step 7 says
to do what the description of the opcode says. It says to add the two registers specified
by Operand 1 and Operand 2 and store the result in the register specified by Operand 1.
Operand 1 is 0 and Operand 2 is 1. Therefore, we will add the value in register 0 to the
value in register 1. Register 0 has 12 in it, and register 1 also has 12 in it. Added together,
this makes 24. The instruction says to store the value in register specified by Operand 1.
Operand 1 is 0, so we will store the result in register 0. Therefore, erase what is currently
in register 0 and write 24 in it.
Register 0 now has the value we want (24 is 12 * 2), but the goal was to get it stored
in memory location 63. So what do you think the next instruction might do? Step 8 says
to repeat the process to find out.
Following steps 1–4 will give us the next instruction: 25, 63, 0. Step 5 tells us to
increase the Instruction Pointer to 12. Step 6 tells us to look up the meaning of opcode 25
in the opcode list and write it down in the Meaning column. This gives us “Store Memory.”
Step 7 tells us to perform the instructions associated with the opcode. This says to
store the value in the register specified by Operand 2 into the memory location specified
by Operand 1. Operand 1 is 63 and Operand 2 is 0. Therefore, we will take the value in
register 0 (which is 24) and write it in memory location 63, erasing what is currently
there. Therefore, write 24 into memory location 63.
55
Chapter 5 How Computers Work
56
Chapter 5 How Computers Work
Now, before we go through the program step-by-step, let’s think about what needs to
happen to do this procedure. First, we will need a place (probably a register) to hold the
current results of the sum as we go through the numbers. As we go along, we will need
to check each number to see if it matches our sentinel value, 255. We need to get the
computer to do something different if it hits the sentinel value than if it doesn’t. Finally,
we will need a way to repeat steps, since we don’t know how many times we will be
doing the calculation.
The way to accomplish all of this is with comparisons and conditional jumps. That is,
we will compare two numbers and, based on the results of that comparison, potentially
change the instruction pointer to tell the computer to run different code. Since we look
at the instruction pointer to retrieve the next piece of code, if an instruction modifies the
instruction pointer, then we will do a different task than we would otherwise have.
The other feature we will look at is indirect mode. Since we will be looking at an
unknown number of different values, we cannot put the location of the value to load
in our code. Therefore, what we will do is use a register to hold the address of the first
value and then use indirect mode to tell the computer to load the value from the address
stored in the register. From there, we can add one to the value in the register to have it
point to the next location in memory.
So now, let’s run through the simulation using the steps in Figure 5-2. Instead of
going through each step like we did in the previous program, I am going to assume that
you now know how to work the steps. Each paragraph is the entirety of the eight steps.
I will focus on the meaning of each instruction rather than all of the steps to perform it.
Performing the steps is your job, but be sure to do all of the steps in the right order. Also,
in order to make what is happening more understandable, as we go along we will be
writing names on our registers so we know what they are doing. The computer doesn’t
use this—this is entirely for our own purposes so we know what each register is being
used for.
The first instruction is 20, 0, 0. This says to load register 0 with the number 0.
Register 0 will hold the sum of all of the numbers. You might go ahead and label register
0 as “sum,” so you can remember what it is for. Remember, the computer doesn’t care
what it is for—the computer just does what you tell it. But you need to remember what it
is for, so you can understand the program.
The next instruction is 20, 3, 255. This says to load register 3 with the number 255.
This is our sentinel value and will be used for comparison. You might label register 3
with the word “sentinel.”
57
Chapter 5 How Computers Work
The next instruction is 20, 1, 57. This says to load register 1 with the number 57.
This is the beginning of the locations that we will be reading the values from. Note that
we are storing the number 57 into register 1, not the contents of memory location 57.
That will come later. Label register 1 with the word “pointer,” since it will point to the
location in memory that we are reading values from.
The next instruction is 20, 5, 1. This says to load register 5 with the number 1. This
is the number that we will use to increment the memory location pointer. Label register 5
with the word “increment.”
Take note of what the instruction pointer currently is. It should be at 12. All of the
previous instructions were “setup” instructions that were meant to get the ball rolling.
The next instruction will really start the process. You should label memory location 12
with the words “main process start” to remind yourself that this is where the core of the
process will happen.
The instruction here at memory location 12 is 23, 2, 1. This says to look in register
1 and use that value as the memory location to look in. Right now, register 1 has the
number 57 in it. Therefore, look in memory location 57 and put that value in register 2.
Label register 2 with the words “current value.” It should have the value 10 in it.
If you think back to what we are trying to do, the next thing we need to do is
determine whether or not the current value is our sentinel value or not. Therefore,
we have to compare our current value (register 2) with our sentinel value (register 3).
However, since in this machine language comparisons overwrite one of the values
being compared with the results of the comparison (look at the Compare instruction
in the tables), we have to first copy one of the values to a new register so it doesn’t get
destroyed. Therefore, the next instruction reads 21, 4, 3. This says to copy the contents
of register 3 (the sentinel value) to register 4. Label register 4 with the words “sentinel
comparison.” It should have the value 255 in it.
The next instruction is 37, 4, 2. When you look up that instruction, it says to
compare the value in register 2 (the current value) with the value in register 4. If they
are equal, it will store the number 0 into register 4. If the value in register 2 is greater
than the value in register 4, it will store a 2 in register 4. Finally, if the value in register 4
is greater than the value in register 2, it will store a 1 in register 4. This way, at the end of
the comparison, register 4 will contain the result of comparing the current value with the
sentinel. Since register 4 had the value 255 and register 2 has the value 10, the value in
register 4 should be erased, and, in its place, you should write the number 1 since 255 is
greater than 10.
58
Chapter 5 How Computers Work
Now that we have the comparison, what do we do with it? The next instruction is
65, 33, 4. This instruction says to look at register 4. If the value is 0, then change the
instruction pointer to 33—otherwise, do nothing. This is a conditional jump. Basically,
it says if the previous comparison of our current value to the sentinel showed that they
were equal (gave the value 0), then go to the end of the program (which is at memory
location 33). Since register 4 contains a 1, nothing happens and we go to the next
instruction like normal.
The next instruction is 133, 0, 2. This adds the contents of register 2 (the current
value) to register 0 (the sum so far) and stores the result in register 2. Since register 0
currently is at 0, it should now be 10 + 0, or 10.
Now we need to do the same thing to the next value. But how do we get to the next
value? Since register 1 holds the pointer to the next value, we just need to increase
register 1 by 1, which is stored in register 5 (the increment). The next instruction is
133, 1, 5. This says to add the contents of register 5 (the increment) to register 1 (the
pointer) and store the result in register 1.
Now we are all set to do the same computation on the next value. We just need to go
back to the right place in our code to do it all over again. The next instruction is 64, 12, 0.
The instruction for 64 is an “unconditional branch.” This means that we directly modify the
instruction pointer to be 12. Therefore, on the next instruction, you will go back to memory
location 12 to get the next instruction. We labeled this earlier with the words “main process
start.” Label this location in memory (30) “main process end.”
Now, I’m not going to walk you through all of the next steps, as you will just be
going back through the same steps repeatedly. However, think about what happens
when you do load in the value 255 from memory? At that point, our comparison above
will notice that the value in register 4 (sentinel comparison) is equal to the value in
59
Chapter 5 How Computers Work
register 2 (current value) and will therefore store the value 0 in register 4. Then, the next
“Jump if Zero” instruction will actually work—the value in register 4 will be zero, so we
will modify the instruction pointer to point to the location specified in the instruction
(which is 33).
At that point, we will load the instruction at memory location 33, which is 25, 56, 0.
This stores the value of register 0 (the current sum, which is now the final sum) into
memory location 56. Memory location 56 should now contain the sum of the relevant
values (i.e., 25).
The next instruction is 0, 0, 0, which tells the simulation to stop. We are now
finished, and memory location 56 holds the value of the sum of memory locations
57, 58, and 59.
Just as before, this is much easier in JavaScript. A similar function in JavaScript would
look like Figure 5-6.
Again, I don’t expect you to understand what this means yet, but you should at
least recognize that this will be much easier than writing out numbers for machine
instructions!
Hopefully this exercise has helped you understand the precision with which
computers perform their processing and the exactness required from the programmer.
If even one of the instructions for the computer programs were written incorrectly, the
whole program would fail. While you probably won’t ever need to do this again, the goal
was to get your brain in line with the way that computers think. This will make thinking
about programming much easier in the future.
If you enjoyed this process, a few other machine language programs are available in
Appendix E.
60
Chapter 5 How Computers Work
Each opcode is listed along with what types of operands it uses. The operands are
the list of values that will be used for processing the instruction. For instance, for an add
instruction, the operands would be the locations which hold the values to be added
together and where the result should end up. This simulated machine has four types of
operands:
The first set of instructions we will look at are the load/store instructions (Figure 5-7).
These instructions simply move data around between storage locations. They also make
the most use of the different operand types discussed above.
61
Chapter 5 How Computers Work
The next set of opcodes are the arithmetic opcodes (Figure 5-8). These are opcodes
that modify values by adding, subtracting, etc. In our simulated machine, there are
very few arithmetic opcodes, but most real computers have a fairly large set of them.
Nonetheless, even with our limited opcode list, a lot can be done with them using a little
creativity. Note that the comparison opcode is included in this list.
62
Chapter 5 How Computers Work
The last list of opcodes are the jump instructions (Figure 5-9). These instructions
cause the instruction pointer to change, usually based on a certain condition. The
conditions are made to match the results of the Compare opcode above (i.e., 37). A
common pattern is for a Compare instruction to be followed by a conditional Jump
instruction based on the result of the Compare. We don’t use the indirect versions of the
jump instructions in this book, but they are listed here because they are very powerful
and important features available in all general-purpose processors.
63
Chapter 5 How Computers Work
That’s it! That is all that computers are. Even though it may seem confusing, the
fact that you can write out all of the rules in a few pages is pretty amazing. Computers
really are simple at heart. The confusion most people make is thinking that they are
complicated. But really, they just do exactly what you tell them. Exactly.
64
Chapter 5 How Computers Work
While performing these minute calculations may seem overwhelming to you, to the
computer they are rather simple. In fact, it is their simplicity that makes it possible for
computers to run quickly. Modern computers can perform around 5,000,000,000 of these
types of instructions every second. They have to be that fast in order to keep up with the
latest software. Every time you move your mouse, the computer has to do very similar
operations as the above in order to recalculate the new mouse position and redraw your
cursor on the screen. You might have noticed that even with 5,000,000,000 instructions
per second, sometimes it is still not enough!
OPCODE NUMBERING
You might be thinking that the numbering system for the opcodes is kind of strange. However,
the numbering system actually has a very logical ordering, but this plan is only evident if you
write out the numbers in binary. Each opcode is a combination of a general instruction type
(load, add, jump, etc.) and the types of operands that it takes, with 2 bits dedicated to each
operand. This is often true of computers—what may seem arbitrary or strange oftentimes
makes a lot more sense with a little more knowledge.
Don’t worry, I don’t expect you to go through and convert the opcodes into binary—after all,
this is just a toy system to help you understand how these things work. But nonetheless,
keep in mind that not only computers but all of life is filled with things whose logic may not
be directly visible but is knowable if you are willing to dig a little deeper and look beneath the
surface.
5.5.1 Review
In this chapter, we covered how machines really work. We have learned the following:
• The main parts of the computer are the CPU, the computer memory,
the input/output system, and the data bus.
65
Chapter 5 How Computers Work
2. Did you notice that the code and the data were both in the same
memory? By storing everything as numbers, both code and data
can be stored using the same system. What problems might
you run into if you accidentally overwrote an instruction with a
data value?
3. Choose one of the programs from Appendix E and see if you can
run it successfully.
66
PART II
69
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_6
Chapter 6 The HTML File Format
Figure 6-1 shows what a marked up document looks like. Since manuscripts were
written by hand or using a typewriter, authors couldn’t type the document in the font
that they wanted, so they put in these markup annotations to tell the printer what to do.
“Helv 12” tells the printer to make the font 12-point Helvetica; “BF” means to use a bold-
faced font; and “FR” means to flush the text right. These types of instructions tell the
printer exactly how to typeset each piece of text. Sometimes that can get tiresome, and,
instead, the instructions to the printer tell them what function the text serves, and then
a separate sheet tells how to typeset that function. In this example, “CT” tells the printer
that the marked text is the chapter title, so the printer also knows to put that title into
the page header at the top of each page. Sometimes the markup would tell the printer
exactly what to do (e.g., “Helv 12” says to use 12-point Helvetica font), and sometimes
the markup would tell the printer the function of the text in the document (e.g., “CT” tells
the printer that the text is a chapter title). If the author specified the function of the text,
they would also supply a separate sheet telling the printer how each type of text piece
should be handled. This idea of separating the structure and function of the document
from the way that it is displayed is something we will return to in Chapter 7.
70
Chapter 6 The HTML File Format
71
Chapter 6 The HTML File Format
PRACTICE ACTIVITY
1. Open your text editor, and type in the HTML document shown in Figure 6-2 into
a new file.
3. Open up your browser. Rather than typing in a URL, go to the “File” menu and
choose “Open.” Open up the file you just saved.
4. Observe how the browser displays each piece of tagged text.
5. Also observe the location bar of your browser. If it tells you the protocol, notice
that it is not an HTTP URL but rather a file: URL. This is because it is getting
the file from your hard drive and not from a web server.
6. Go back to your text editor and add a new heading and a new paragraph of text
and save it.
8. Add extra spaces between words and before and after tags. Save the file and
reload the browser. Did anything change? Other than separating text into words,
blank space (termed whitespace) is not used in HTML. If you need to alter
spacing, you have to use tags to tell the computer what you want to do.
1. All tags are enclosed in angled brackets (i.e., < and >).
2. For nearly every tag, there is a start tag and an end tag. For the
paragraph tag, the start tag is <p> and the end tag is </p>. The only
difference between them is that the end tag has a forward slash (/)
before the tag name. If you forget the end tag, many browsers won’t
complain, but you may get strange results.
72
Chapter 6 The HTML File Format
3. Pairs of start and end tags must be fully within other pairs of start
and end tags. For instance <p>hello <i>there</p></i> is not
allowed, but <p>hello <i>there</i></p> is allowed. In the first
example (which is incorrect), the <p> tag starts before the <i> tag,
but the end tag </p> occurs before the end tag </i>. Therefore, the
<i> </i> pair is not fully within the <p> </p> pair.
4. For the few tags that do not have an end tag, you combine the
start and end tag together. <br> does not have an end tag, so it is
written <br />. This is called a self-closing tag.
5. The combination of a start tag, end tag, and their enclosed content
and tags is called an element. <p> is a tag but <p>hello</p> is an
element.
From here on out, I will only refer to a tag by its start tag. You should always assume
that the start tag requires an end tag unless we explicitly say otherwise.
Now, you may have noticed that in our original HTML example, there were several
tags that didn’t seem to do anything—namely <html>, <head>, and <body>. The <html>
tag is known as the document root tag. It is the tag that contains all other tags and is
required to be there. In this book, if you see an example that doesn’t have an <html> tag,
then it is only showing you a fragment of the document—the rest is assumed to be there,
but we are only showing the important parts to make the example clearer. The first tag
of every document should be an <html> tag, and every document should end with an
</html> end tag. The <head> tag includes tags that tell the browser about the document,
but which are not displayed within the document itself. In the example given, the <head>
tag contained a <title> tag, which told the browser what the title of the document was.
The browser probably displayed this title in the top of the window and would also use
it if you bookmarked the page. The <body> tag tells the browser that we are starting the
portion of the document which should be displayed.
73
Chapter 6 The HTML File Format
Some basic tags that you will encounter in most HTML documents include the
following:
<title> This tag tells the browser the title of your page.
<h1> This tag is used for the largest heading on the page.
<h2> This tag is for a subheading in the page. HTML has additional
subheading sizes down to <h6>.
<p> This is the paragraph tag. Browsers usually give a blank line
between any two paragraphs.
<br> This is a line break. This tag self-closes and is used to force a
line break anywhere in the document.
Also notice that we began our file with <!DOCTYPE html>. This is called the doctype
declaration and tells the browser that, yes, this really is an HTML document.
74
Chapter 6 The HTML File Format
PRACTICE QUESTIONS
2. Which of the following HTML fragments use tags in an invalid way? Why?
(a)
<h1>My Heading</h1>
(b)
<h1>My Heading</h1>
(c)
<h1>My Heading</h1>
3. Open up any web page on the Internet. View the HTML source of the web page
(see Appendix B.4 for instructions on doing this). Try to identify tags from the
list above.
4. In a previous practice activity, you created an HTML file. Modify your HTML file
using some of the tags in the list above.
75
Chapter 6 The HTML File Format
1
Note that in computer programming, you should never use the curvy quotes that your word
processor uses. It is actually fairly problematic to type something into a word processor and then
copy and paste it into a document. The reason is that word processors often auto-convert straight
quotes (") into curvy quotes (“). This is an error in most programming and markup languages.
76
Chapter 6 The HTML File Format
<img /> This tag is used to include an image into the page at
the location where the tag is placed. The src attribute tells the
browser where to find the image. Note that <img /> is a self-
closing tag. Using the tag <img src="https://placekitten.
com/200/300" /> will place a cat image into your web page.
<link /> This tag is used to connect style sheets to your HTML
page. We will cover more about style sheets in Chapter 7. Note that
<link /> is a self-closing tag.
77
Chapter 6 The HTML File Format
As you can see in this example, the <a> tag creates a link to another document. The
document to link to goes in the href attribute, and the text to link to goes between the
start and end tags. Then, at the end, the <img /> tag refers to an image file at a specified
URL and includes that within the page.
PRACTICE QUESTIONS
• Create a new HTML file using the example document in this section. View it in
your browser to make sure you entered everything correctly.
• Modify this HTML file. Add links for all of your favorite places to go on the Web.
• Find an image on the web that you like. Find out its URL (see Appendix B.5). Add
that image to your web page.
78
Chapter 6 The HTML File Format
The second file will have a link back to the first file that looks something like this:
This is rather tedious, especially since they are in the same directory (i.e., www.
example.com/fruit).
The HTML standard gives us three choices of what to do. The regular URL, also
called the fully qualified URL or absolute URL, that we have been using contains
all of the data necessary to connect. The relative URL takes most of its connection
information from the current URL, which, for linking purposes, is also called the base
URL. So, in the previous example, if we were already looking at www.example.com/
fruit/apples.html, we could link to the other file just by referring to oranges.html
like this:
This is a relative URL and it tells the browser to look in the same folder that we are
currently in, but just change out the last part of the URL so that it points to this new
file. Using relative URLs not only gives us less typing, but it also makes it easier to move
groups of documents. As long as apples.html and oranges.html stayed in the same
directory together, you could move them around to be under a different site or to a
different directory on your site, and their links would still work. In short, relative URLs
use the current URL, up to and including the current directory, as the starting point. The
relative URL just tells how to get to the document from where you already are. You can
tell a relative URL from a fully qualified URL by the fact that it doesn’t include a protocol
and it doesn’t start with a slash.
There are two other kinds of URLs which are hybrids between absolute and relative
URLs. The first is the absolute path. The absolute path tells the browser to use the
current protocol and server but replace the path entirely with the one specified. In our
example, the absolute path to apples.html is /fruit/apples.html. Note that absolute
paths always begin with a slash. If it does not begin with a slash, it is considered a
relative URL.
The final type of URL is the network path. This URL uses the protocol of the current
page, but you specify everything else. So, the network path of oranges.html is //www.
example.com/fruit/oranges.html. Network paths are rarely necessary, but it is good to
know what they mean in case you see them.
79
Chapter 6 The HTML File Format
PRACTICE QUESTIONS
1. Create another simple web page in the same directory as your other
web pages.
2. Create a link from your new page to one of your other pages. Remember to use
relative links!
5. Test out your links. Did they work? If not, check the URL in your browser to see
where the browser thought you were asking it to go.
6.5 Relative URLs
Relative URLs have a lot of features that make them helpful both when building a website
and when using a book like this. For instance, since the files we create will be on your
hard drive instead of a web server, it is much easier to use relative URLs rather than the
extremely long file: URLs that specify where on your hard drive another document is.
In addition, by using relative URLs, it means that the web pages you create will still work
if you hand them in to a teacher or parent. If you use file: URLs, then all of the URLs
would be wrong when your parent or teacher loads them on their computer, because
they would be in a different location on their computer than they were on yours. If,
instead, you use relative URLs, then, as long as you deliver all of the files together, the
URLs will still work in their new destination. For the purposes of this book, every time
you reference a file that you create or that you store on your hard drive, you should use
a relative URL, but when you reference a file stored somewhere else on the web, you
should use absolute URLs.
Another feature of relative URLs is that you can use them to refer to subdirectories.
Let’s say that you want the page at www.example.com/fruit/apples.html to link to the
file www.example.com/fruit/exotic/rambutan.html. You will notice that they share a
lot of their URLs between them. The relative URL tells you how to get to the document
from the current directory. From www.example.com/fruit/ I only have to say that I want
to go to exotic/rambutan.html. Therefore, I can link to this page like this:
80
Chapter 6 The HTML File Format
Now, let’s say that I am writing the page on rambutans, and I want to see my page on
apples. How does that work with relative URLs? There is a special directory name that
refers to the enclosing directory (also called the parent directory). This is referred to
with two periods (i.e., ..). If you are writing the page www.example.com/fruit/exotic/
rambutan.html and you want to link to www.example.com/fruit/oranges.html, you can
write the link like this:
<a href="../oranges.html">oranges</a>
You can include as many directories as necessary in your URL. For example, if you
were writing the page www.example.com/fruit/exotic/rambutan.html and wanted to
link to the page www.example.com/fruit/poisonous/snowberry.html, you would write
the following:
One other important special directory name is the . directory. While the two periods (..)
refer to the parent directory, the single period (.) refers to the current directory. This is rarely
used in HTML, but you will see it on occasion.
6.6.1 Entities
Because HTML uses the < and > characters to signify that the given text is a tag, how
would you then actually write those characters? HTML provides entities to refer to
characters that either have a special use by the HTML format or are hard to type (e.g.,
characters from other languages). An HTML entity starts with an ampersand (&) and
ends with a semicolon (;). Common entities include:
81
Chapter 6 The HTML File Format
> >
< <
& &
" "
' ’
© ©
6.6.2 Lists
Lists are great ways of organizing things in HTML. A list can either be unordered (i.e.,
a bulleted list) or ordered (i.e., a numbered list). The tag that encloses the whole list is
<ul> for an unordered list or <ol> for an ordered list. Then, each list item is enclosed in
an <li> tag for both kinds.
Figure 6-5 shows a short HTML fragment that illustrates how these lists are used. The
first list will display as a bulleted list, while the second list will be numbered.
6.6.3 Table Tags
In addition to paragraphs, headings, and lists, people often need to represent tables of
data on web pages. HTML has a set of tags specialized for displaying tables of data. Let’s
say we wanted to make a list of our friends, with their name, their email, and their phone
number. We would want the first row to be the headings (such as “Name,” “Email,” and
“Phone”) and the other rows to be the data. For that, we will need several tags:
82
Chapter 6 The HTML File Format
<td> This tag wraps around the contents of a single data cell.
<th> This is just like the <td> tag, but it is used for headings (it
usually makes the content bold).
<tbody> This tag is also not strictly necessary, but it is often used
to wrap around rows of data in your table.
<tfoot> Just like the <thead> tag, but used for footers of tables.
Figure 6-6 is a fragment that shows how we can put these tags together to make
a table.
This will display something like this:
83
Chapter 6 The HTML File Format
6.6.4 Form Tags
A lot of web pages allow you to enter data. Data entry web pages are commonly referred to
as “forms.” These tags allow the user to enter in their own values. They won’t be useful until
we know how to process them, but we will list some of those tags for future use. Notice
that the <input /> tag can actually be several different input elements. The element that
is displayed on the page is chosen based on the type attribute. The <input /> tag should
also be written as a self-closing tag.
<form> This tag normally encloses other form tags. If the form is
supposed to submit data to a server, that destination is usually put
in the action attribute.
84
Chapter 6 The HTML File Format
Most of these tags also have a name attribute that you can use to specify what the field
is for (this will be important later) and a value attribute to give the field an initial value
or, in the case of check boxes, to give the value that this box represents.
Figure 6-7 shows an example HTML fragment for a form (note that this doesn’t
actually do anything; it just lets the user interact with it).
6.6.5 Standard Attributes
There are a few attributes which are standard for every HTML element. There are three
that are important to this book: id, class, and style. The id attribute essentially gives
a name to your HTML element that is unique within the document. We can use this
attribute to locate the element for processing by JavaScript or for styling. Note that the
browser won’t complain if there are two elements with the same id attribute on the same
page, but it could cause subtle errors.
85
Chapter 6 The HTML File Format
The class attribute is more of an ad hoc attribute—you can basically use it for
whatever you want. Usually, it is used to group certain items together that should be
given a similar style or where an entire group of elements should be processed by
JavaScript.
Finally, the style attribute can be used to explicitly set styling information (see
Chapter 7) on an element.
86
Chapter 6 The HTML File Format
This is called commenting out code, because you are taking the code out of the document
or program using comments.
So what does a comment look like? Comments are simple. They start with <!-- and
they end with -->. Here is a short HTML fragment with a few comments:
The only processing instruction you are likely to see is this one, known as the XML
declaration:
87
Chapter 6 The HTML File Format
If used, this goes at the beginning of the document, before the doctype declaration,
and even before any blank lines or whitespace. It tells the browser to use special, more
strict rules when processing the HTML document. For instance, if you don’t use this tag,
the browser is much more forgiving for small violations of the HTML standard.
One last feature that is sometimes seen is CDATA sections. A CDATA section is most
often used when you have a lot of angled brackets to write in the document itself, but
don’t want to have to write entities for each one. A CDATA section tells the browser to
just treat the text as literal text and don’t try to find tags, comments, or entities. CDATA
sections start with <![CDATA[ and end with ]]>.
Figure 6-8 shows a short example.
Many browsers don’t fully support CDATA sections in all circumstances, so it is best
not to use them, but it is good to know what they are in case you see one.
6.6.7 Review
In this chapter we covered the basics of HTML, what it is, and how to write it. We have
learned the following:
• A markup language is a text document that uses tags (which are also
text) to specify the structure and function of the different pieces of the
document.
88
Chapter 6 The HTML File Format
• The id, class, and style attributes can be applied to any tag.
89
Chapter 6 The HTML File Format
90
CHAPTER 7
Introduction to Cascading
Style Sheets
7.1 The Origin of Cascading Style Sheets
When HTML was first developed, it was entirely used for communicating information.
HTML was originally built as an easy way to browse and view documents. Therefore,
HTML documents were never pretty but were very functional. In addition, there was a
direct match between the tag used and the purpose that the tagged text served in the
document. For instance, <h1> tags meant that the given text was a main heading. If you
were looking at the HTML code itself, you would know precisely what it meant if you
found text with that tag. In fact, if you knew the tags, you could almost just as easily read
the document source with the tags as you could read it rendered in the browser.
However, as more and more people started using the Web, HTML started serving
more purposes than purely informational ones. The modern web is much more user-
focused and incorporates many other types of media and functionality, including
navigation, entertainment, advertising, and branding. In the early days, in order to
accommodate for these new uses, HTML’s tag and attribute set expanded and expanded.
The problem was, however, that the initial beauty and simplicity of HTML was lost.
Web pages became complicated messes of undecipherable tags. In addition, different
browsers rendered the tags slightly differently. Therefore, in order to write a web page,
you had to know not only what each tag did but how the tag would look in every browser
and how to get them all to work together to produce a good-looking web page.
The organizations that control the standards for the Web recognized this problem
and decided to move HTML back closer to its roots. In order to achieve this, they
attempted to separate content from presentation. Content refers to the data that the
web page is intended to communicate. Presentation refers to how that page will look to
91
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_7
Chapter 7 Introduction to Cascading Style Sheets
the user. Headings, paragraphs, figures, etc. are all part of the content. The background,
formatting, layout, colors, fonts, and decorations are all part of the presentation.
In order to do this, they removed styling from HTML and created a new language,
called Cascading Style Sheets (CSS for short), to tell browsers how the HTML should
look. In this new paradigm, the structure and content of the document is written in
HTML. How that content should be laid out, formatted, and presented is written in
CSS. The advanced interaction between the user and the content is written in JavaScript.
This separation is not perfect, but it is a huge improvement.
It is interesting to note the way that technology progresses. The way HTML progressed is
very similar to many other technologies. The first version was very simple and direct. It
accomplished the needs of its users very well.
However, its success led to many problems. Because everyone was using it, new people, with
different needs than the original users, were also using it. In order to accommodate this, they
simply added a bunch of features to HTML. However, it quickly became apparent that simply
adding features was making a mess of things. It did expand the capabilities of HTML but at the
cost of making all HTML work more complicated (and expensive).
The next step in the progress of HTML was to reevaluate the different aspects of how HTML
worked and the different needs they served. As it turned out, there were several needs that
were plainly distinct. There was the need to handle content, the need to display content in a
visually pleasing manner, and the need to make the content interactive.
Because these needs were distinguishable, they were then refactored into entirely separate
pieces. HTML would handle the content, CSS would handle the presentation, and JavaScript
would handle the interactivity. HTML was a great content language, but a bad styling language.
So this new setup allowed HTML to do what it did best and left styling and interaction to other
technologies which were better suited for the task.
92
Chapter 7 Introduction to Cascading Style Sheets
happens when the growth of a technology causes it to become overly complex. At that point,
it needs to be reevaluated to find if there are simpler components that the technology can be
divided into.
Refactoring is not a panacea and must be used judiciously. If refactoring is done prematurely,
all of the different components may not be clearly seen, and it may be refactored in ways that
make progress more difficult rather than less. However, for the most part, refactoring tends to
give new life to old technology as it increases both flexibility and understandability.
Now, create a document called basic.html in the same directory as basic.css with
the contents as shown in Figure 7-2.
The part of the file that links together these two files is the <link> tag. The <link>
tag can be used to specify all sorts of related documents (what it is linking is specified
by the rel attribute), but its most important usage is to specify the style sheet to use for
a web page. The document that the <link> tag refers to is listed in the href attribute.
So, in short, the <link> tag in the document above says to use the file basic.css as its
style sheet.
93
Chapter 7 Introduction to Cascading Style Sheets
If you open this file with your browser, you will find that, indeed, it renders the
document as we specified. If it doesn’t, go back through and try to find your mistake (to
start with, be sure they are both in the same directory).
The CSS file format is fairly simple and straightforward. It consists of two major parts:
selectors and properties. CSS properties list out the styles to be used, and CSS selectors
tell which pieces of HTML those styles are to be used on. So, in the file we were looking
at, h1 and p were the selectors. The selector was followed by a property list wrapped in
curly braces ({ and }). The property list tells what styles to use on the text.
The two properties we use in Figure 7-1 are color, which defines the color to make
the text, and font-size, which tells what size font to use for the text. CSS2 defines 98
different properties available to use, and CSS3 defines even more. However, there aren’t
that many properties that you need to know to get started. This chapter will only cover
the most important ones, but you can see a fairly comprehensive list of CSS properties at
www.w3schools.com/cssref/.
94
Chapter 7 Introduction to Cascading Style Sheets
7.3 Understanding Selectors
The CSS selectors used in the previous section listed the tag name that was to be styled.
However, such a selector has limited use and will not give us the kind of flexibility
needed to produce really nice documents.
Let’s say, for instance, that you have different types of paragraphs that you wanted
to lay out in different ways. You want one paragraph to be red text on a blue background
and another paragraph to be green text on a black background. In order to do this,
the CSS file will have to be able to distinguish between these two different types of
paragraphs, but HTML only provides one paragraph (<p>) tag. To accomplish this, CSS
can also use attributes to choose which tags that a set of properties applies to. In order
to facilitate this process, HTML defines a class property available on all HTML tags,
which can be used for whatever purpose the writer wants. Usually, they are used to make
distinctions between tags for CSS to process.
95
Chapter 7 Introduction to Cascading Style Sheets
Now let’s take a look at how the styles specified in Figure 7-4 work on the HTML. The
first selector is just like before—it is a tag name followed by styling properties. It says that
paragraph tags should have a font size of ten points.
The next selector, however, is different. This selector says p[class=style1], which
means that it applies only to <p> tags that have the class attribute set to the value
style1. The properties for this say that paragraphs with the style1 class should be red
text on a blue background. Note that a <p> tag with the style1 class would also match
the first selector, since the first selector applies to all <p> tags. Therefore, any attribute set
in the original selector would still be applied, so it uses a ten-point font as well.
96
Chapter 7 Introduction to Cascading Style Sheets
The final selector is just like the previous one, except that it is set to match
paragraphs with a class of style2. It displays the paragraph with green text on a black
background. It also sets the size of the font to 12 points. This is in conflict with the setting
that was set in the first group of CSS properties, which set all <p> tag sizes to ten points.
However, because the selector for these properties is more specific, its properties supersede
the ones from the more general selector.
You can select HTML elements by any attribute you want. However, selecting by the
class attribute is very common. In fact, it is so common that there is a special simplified
notation for selecting by class. Instead of writing p[class=style1] for a selector, I can
just write p.style1 as a shorthand.
Therefore, if I were to rewrite my classes.css file using this simplified notation, it
would look like Figure 7-5. Not only is that easier to write, but it is easier to read!
CSS has a rich supply of selectors that allow you to style documents in a very
dynamic way. You can have selectors that indicate tags that are within other tags, tags
that are preceded by some other tag, and a number of other ways of selecting HTML
elements for styling. This book, however, only covers the very basic elements of CSS that
you will need on your way to understanding how to program web pages, so we won’t go
into any more depth on CSS selectors.
97
Chapter 7 Introduction to Cascading Style Sheets
• The background, if set, extends behind the content, the padding, and
the border.
98
Chapter 7 Introduction to Cascading Style Sheets
• The margin is the area outside the border. The margin is a little
different, however, as it is the minimum amount of space between
one element and the next, so if two elements next to each other both
have a margin set, it simply uses the larger of the two margins (it
doesn’t add them together).
The size of the content area can be set manually using the width and height
properties. If the width is not set, then the width is automatically set so that the entirety
of the box (including content, padding, border, and margin) fit the entire width of the
containing box (or the screen if there is not another containing box). Then, given the
determined (or manually set) width, the height is set to whatever is required to contain
the content. Oftentimes you don’t see all of these pieces (especially the border) because
they are zero-width. However, you can, using CSS, set the size and other properties of
each one of these aspects of any box.
Inline content, because of its irregular shape, can have padding and a border, but
the margin works strangely. Essentially, for inline elements, the top and bottom margin
are ignored, but the left and right margin are utilized at the beginning and ending of the
elements. However, if the inline content spans multiple lines, the left margin is only used
on the first line, and the right margin is only used on the last line.
If you go back to the HTML from Figure 7-3, we can modify the CSS style sheet
(classes.css) to show how the box model works. The HTML is divided into two sections
by <div> tags. We will set each <div> tag with a border, a background, a padding, and an
internal width. Figure 7-7 shows the code to use.
99
Chapter 7 Introduction to Cascading Style Sheets
This gives us two large boxes, one for each section, and several smaller boxes.
Remember, unless otherwise constrained, the boxes take up as much width as they can.
The top box takes up the width of the page (minus the margin around itself ). The boxes
within that box also take up as much width as they can, but they are constrained by the
margin, border, and padding of the box around them.
The second box does not go all the way across the screen because we set the width
of that box to be 50%. Therefore, it only goes halfway across the page. Likewise, the boxes
within that box are constrained to this new size.
While we have set the margin, padding, and border on all sides to be the same value,
we can also set them to be different on different sides. Instead of just using padding, we
can instead set padding-right, padding-left, padding-top, and padding-bottom to
separate values.
So far, we have seen several different units for the sizes of things in CSS. CSS has several
units of measure available, but the most common are pt for points, px for pixels, in for
inches, mm for millimeters, and % for percentage of the containing size. Additionally, CSS also
has a few units that are relative to the currently selected font size. The em is the size of the
letter “m” in the current font, ex is the size of the letter “x” in the current font, and ch is the
size of the “0” in the current font. The rem is the size of the letter “m” in the font size of the
root element of the page. The rem unit is very popular because, if used everywhere, it allows
auto-scaling the entire web page by simply changing the size of the font on the root element.
100
Chapter 7 Introduction to Cascading Style Sheets
7.5.1 Review
This chapter covered the basics of Cascading Style Sheets. We have learned the
following:
101
Chapter 7 Introduction to Cascading Style Sheets
• CSS allows HTML to hold the content of a web page without regard to
how it will be displayed.
• CSS selectors are often based on the names of tags and the values of
attributes.
• CSS lays out a page on the basis of the CSS box model, in which each
HTML element is assigned a rectangular box on the page and has its
own padding, border, and margin.
• Because the styling for a page or set of pages lives in an external file,
CSS allows the look of an entire website to be changed by updating
only the shared CSS file.
2. Create a new HTML file with a new CSS file. Create four
rectangles on the screen with different widths, heights, and
background colors.
102
Chapter 7 Introduction to Cascading Style Sheets
your imagination is more than what you know how to do. Just do
what you can! Feel free to also look on the web for additional CSS
properties you can use to make your design come to life. Sites like
w3schools.com have a wealth of information on CSS creation.
103
CHAPTER 8
105
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_8
Chapter 8 Your First JavaScript Program
There have been other technologies that also make web pages more dynamic, such
as Java, Flash, Silverlight, ActiveX, and other plug-ins, but these have not been nearly as
integrated into HTML documents as JavaScript. These other technologies usually work
by taking a specific area of your web page away from the browser and handling it itself.
JavaScript, on the other hand, works as an integrated part of the web page itself. These
other technologies were developed to augment areas where JavaScript fell short, such
as animation, video, and integration with other parts of your computer (such as your
camera) which are not normally part of the browsing process. JavaScript, however, has
been slowly taking over these tasks as well, and today there is hardly any aspect of your
browsing experience that isn’t available through JavaScript. JavaScript has withstood the
test of time and continues to prove its usefulness.
One confusing thing about JavaScript is the name. As mentioned in the previous
paragraph, there is another, different web programming language called Java. These
are not the same thing, nor are they even very similar. It is important to always refer to
JavaScript by its full name, because it works and acts significantly different from Java.1
Over the years, support and standardization of JavaScript has increased dramatically.
In the early days of JavaScript, each browser handled JavaScript very differently, and
it was difficult to write JavaScript that worked everywhere. Now, 30 years later, the
situation is much improved. JavaScript was standardized by the ECMA under the name
ECMAScript. Though it is standardized under a different name, this is the same language
as JavaScript.
JavaScript is now by far the most standard way of developing interactive web pages.
It is installed on every major browser, and almost all of the inconsistencies between the
versions have been worked out. It is also supported by numerous third-party developers
who write programming libraries (add-in functional modules) that provide JavaScript
programmers with the ability to do just about anything imaginable.
1
While Java was originally built as a language which runs in the browser like JavaScript, Java today
is primarily used on the server. JavaScript can also be used on the server, but that isn’t the focus of
this book.
106
Chapter 8 Your First JavaScript Program
107
Chapter 8 Your First JavaScript Program
The first thing to notice is the <script> tag. This tag tells the browser that what
occurs between the <script> start and end tags is JavaScript code. The browser will start
running this code as soon as it comes across the end tag, even before it finishes loading
the page. There are two possible attributes to the <script> tag. The one used here is the
type attribute, which tells the browser what language the script will be in. This should
always be text/javascript. The <script> tag can take another attribute, src, which
tells the browser to look in another file (designated by the value of src) for the JavaScript
code instead of it being in the web page itself.
After the <script> tag, there is a JavaScript single-line comment.
Whenever JavaScript code has two slashes together, from that point to the end of the
line is considered a comment and ignored by the browser (see Section 6.6.6 for more
information about comments). Another type of comment you will see in JavaScript starts
with /* and ends with */ and is intended for comments which span multiple lines.
The first set of programming statements start with the word var:
var person_age_string;
var person_age_number;
var age_in_twenty_years;
var tells JavaScript that we need a temporary storage space, called a variable,
to hold some data and gives that temporary storage space a name. Therefore, var
person_age_string says that person_age_string is going to be the name of a temporary
storage space which we will use to hold data. The way programmers state this is that var
person_age_string creates a variable called person_age_string. This is also referred
to as defining or declaring a variable. When we refer to person_age_string later, it will
refer to this variable.
After this is a semicolon (;). In JavaScript, semicolons are used to separate
statements from each other. So when we see a semicolon, we know we have come to the
end of a statement.
The next two statements are just like the first, defining the variables person_age_
number and age_in_twenty_years. Notice that we are using underscores (_) within the
names of our variables. This allows us as programmers to see the words spelled out,
but it makes sure that the computer knows that they are all one word. For instance, if I
said “I am going to the bus stop,” you know that “bus stop” is really one word. However,
108
Chapter 8 Your First JavaScript Program
computers are not that smart. Therefore, if you were talking to a computer, you would
need to say, “I am going to the bus_stop” (notice the underscore), so that the computer
knows that bus_stop should be treated as one word.
The next statement has a lot more action in it. Here is the code:
There are several important things going on in this line of code. First of all, notice
the equal sign (=). In most programming languages (including JavaScript), the equal
sign is a command that says to put whatever value is on the right side of the equal sign
into the variable on the left hand side. It does not say that these two things are equal
already; it says to assign the right-hand value to the left-hand variable. This is known as
an assignment statement. The left-hand side of this statement is one of the variables we
just defined. This statement says that we should put a new value into that variable. The
right-hand side of this statement tells what the value should be.
The right-hand side is where things get interesting. prompt("What is your age?")
tells the computer to put up a dialog box, ask the given question, and then give back the
value the user entered. This is called a function because it accesses functionality that
is defined somewhere else. Functions in JavaScript start with the name of the function
(prompt in this case), then an opening parenthesis ((), then the function parameters,
and then a closing parenthesis ()). A parameter (also referred to as an argument) is a
value that is sent to a function that the function uses to carry out its functionality. In
this case, the function has one parameter, "What is your age?". This is a character
string—a sequence of characters that are all combined together into a single unit (like we
discussed in Section 4.4). In JavaScript, a string is enclosed in either double quotes ("),
single quotes (’), or backticks (`) and is treated as a single value, although you can also
access the characters individually if you need to.2
We say that the parameter is passed to the function because the function will receive
whatever value we put here. The prompt function can take either one or two parameters.
The first parameter is the text you want to display to the user in front of the input box.
The second parameter (which we are not using here) gives a default value to the user. If
a function takes more than one parameter, each parameter is separated by a comma (,).
So, if we wanted to give the user a default age, we would write it like this:
2
The backticks have some additional functionality, but most of that isn’t important for the present
moment, except that if you want a string to span multiple lines, you will need to use backticks.
Strings using single or double quotes should start and end on the same line.
109
Chapter 8 Your First JavaScript Program
Remember that prompt is working with character strings, not numbers, which is
why we put our default value in quotes. The code does not continue until the function is
finished, which, in this case, means that the user has typed in a value and clicked “OK.”
When the user does type something, that value is then used as the resulting value of the
function. We say that the function returns that value.
Therefore, to use the terminology we have discussed so far, we say that the code
prompt("What is your age?") calls the function prompt with a parameter "What is
your age?" and returns whatever the user types as the value of that function.
Then, since the prompt function returns whatever the user types, the value that the
user types gets stored into the variable person_age_string. Now, why did we call the
variable person_age_string? Since we have no control over what the user types, we are
getting what he types back as a string. We want the user to type in a number, but in reality
he can type anything he wants—there is nothing to prevent him typing nonnumeric
characters. Therefore, the prompt function always returns a string. Hopefully, the user
did what we asked and typed in a number. But no matter what, prompt returned a string.
We named the variable person_age_string so we remember that it is holding a string,
not a number.
Now the program needs to add 20 years to whatever age the user typed. That isn’t
currently possible, because we are holding the string that the user typed in, but we
need a number in order to perform addition. The next line, person_age_number =
parseInt(person_age_string), does the conversion we need. parseInt is a built-in
function that takes a string and parses it into a number. Parsing is the process of taking
a string and converting it into a more computerized representation that is easier for
computer programs to manipulate. In this case, we are taking a string and converting
(parsing) it into a number. parseInt is short for “parse integer,” where an integer is a
whole number (i.e., 1, 2, 3, 4, etc.). If you wanted a number with decimals in it, you would
use parseFloat, which is short for “parse a floating-point number,” with a floating-point
number being a number with a decimal point in it (i.e., 31.25, 0.002, 23.12, etc.).
We then take the value from the parseInt function and store it into the person_age_
number variable. Now we have the value we need in a variable as a number. Since it is a
number, we can perform computations with it!
age_in_twenty_years = person_age_number + 20 tells the computer to add 20 to
the value in the variable person_age_number and then store the result in age_in_twenty_
years. In JavaScript, + and = are considered operators, and the values that they operate
110
Chapter 8 Your First JavaScript Program
on are called operands. Operators are special built-in operations in the language. They
differ from functions because, as we will learn, you can write your own functions, but the
operators of a language are essentially fixed. Operators are used to do special tasks (such
as assignment) or in places where making a function call would look funny. For math
operations, for instance, it is more natural to write 2 + 3 than it is to write something like
add(2, 3).
Now we now have the value we are looking for; all we need is to display it. The next
line of code displays the value.
This piece of code has several strange features. First of all, it uses the plus sign (+)
with strings. How would you add strings? Well, in JavaScript, when the plus sign is used
with strings, it no longer means addition, but rather concatenation. Concatenation
means joining two things together. In this case, we are joining strings end-to-end. There
is one problem—age_in_twenty_years is not a string but a number! JavaScript handles
this automatically by converting anything that is added to a string into a string before the
addition takes place. So, the plus sign indicates addition if it has numbers on both sides
but concatenation if there is a string on either side of it. In addition, concatenation will
convert the other value into a string if it isn’t one already.
Another interesting feature of this code is that it combines several operations. It
concatenates three items together and then passes the resulting string to the alert
function. In most programming languages (including JavaScript), you can combine as
many operations and functions as you want together to give you the final value. The
innermost operations are performed first, and their results are then passed as inputs to
the more outer operations.
Finally, this code introduces the alert function, which displays a popup to the user.
The alert function returns when the user clicks on the “OK” button.
PRACTICE QUESTIONS
2. What are the two different uses of the plus sign in JavaScript?
111
Chapter 8 Your First JavaScript Program
PRACTICE ACTIVITY
In this activity we will try to modify the program in this section. Be sure that you have the
original program working correctly before you begin the activity. Test your program after each
step to make sure it is still working. If you wait until the end, and it doesn’t work, you won’t
know where you made the mistake.
3. Can you figure out how to combine the lines with the prompt and parseInt
into one another so that the output of prompt becomes the input of
parseInt? What variable is no longer needed in this case?
112
Chapter 8 Your First JavaScript Program
In order to put your JavaScript into a separate file, all you need to do is copy the code
between the <script> start and end tags and paste them in a new text document with
the extension .js. Then, modify your <script> tag to have a src attribute (keep the type
attribute the way it is) with the relative URL of your new JavaScript file. If we named our
JavaScript file application.js and put it in the same folder as our HTML file, the HTML
would look like Figure 8-2, and the JavaScript would look like Figure 8-3.
Keeping your JavaScript in a separate file has other advantages as well. First of
all, it makes your HTML pages easier to read because they only have one language in
them—HTML. By keeping your languages separated in their own files, you keep more of
your sanity intact. Another reason is that it allows you to share JavaScript programs and
pieces of JavaScript programs between multiple web pages so you don’t have to write or
copy the same code over and over again. This also means that if you change your code
in one place, you don’t have to search for and make the same change on every other
page, a process which is both tedious and error-prone. If you have a large JavaScript
application, separating your JavaScript can actually make your pages load faster because
your browser only has to load your JavaScript once rather than have it take up space
implanted in the middle of each file.
113
Chapter 8 Your First JavaScript Program
8.3.1 Review
In this chapter, we covered the absolute basics of how to write a JavaScript program. We
have learned the following:
• ECMAScript is the name for the language used by the group which
standardized it, but it is usually still referred to by most people as
JavaScript.
• Variables are storage locations for values and are declared using the
var keyword.
• When functions complete, the value they give back is called the
return value.
• prompt is a function that brings up a dialog box for the user type in a
character string and returns that character string.
114
Chapter 8 Your First JavaScript Program
2. Try to rewrite the program you just created so that it doesn’t use
variables. Hint: Make the return value of your functions be the
parameter to other functions. It also might help to combine code a
piece at a time, eliminating a single variable each time.
115
PART III
JavaScript Fundamentals
This part covers many of the basic principles of programming needed to start
programming in JavaScript.
CHAPTER 9
9.1 Elements of Syntax
While every programming language has its own syntax, there are certain types of
syntactical units (i.e., pieces of syntax) which are common to nearly all programming
languages. For instance, nearly every programming language has a statement
separator—a symbol which tells the programming language that you have ended a
statement. In JavaScript (and many other languages), the semicolon (;) performs this
function. Because programming languages need to know where statements begin and
end, most of them include a syntactical unit in the language which says that we are done
with a statement.
119
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_9
Chapter 9 Basic JavaScript Syntax
Keep in mind that the goal of this book is to provide you with a practical
introduction, not a comprehensive list. There will be aspects of the syntax that we skip
over, briefly mention, or oversimplify. In fact, I can guarantee you that if I gave you all
of the details, you would put the book down and find something else to do! This is not
a hindrance, however. It is actually very rare for a programmer to know all of the details
of the syntax for the language they program in. Some of the details cover situations that
the programmer would never think to do but are included by the person who created
the language for the sake of completeness. So, in any language, you are almost always
a student and rarely a master. The few who are masters are usually the ones writing the
languages themselves. What is in this book should serve you well for a long time, but
keep in mind that there is always more to learn.
9.2 Assignment Statements
In Chapter 8, we covered assignment statements quite a bit. Assignment statements are
the foundation of most programming languages.
An example assignment statement is as follows:
x = 2 + 3;
Assignment statements have two sides—the left-hand side and the right-hand
side. The left-hand side is either a variable or, as we will see in Chapter 11, some other
reference to a location that can hold a value. For this chapter, the left-hand side of an
assignment will be a variable.
121
Chapter 9 Basic JavaScript Syntax
var x;
x = 10; // x currently has the value 10
x = x + 13; // x now has the value 23
If you look at the last statement, the expression is x + 13. Since the value of x is
currently 10 (the value that was assigned in the previous line), then the value of the
expression is 10 + 13, or 23. Since this is an assignment statement, the value of the
expression on the right-hand side (23) is now assigned to the variable on the left-hand
side (x). Now, the value of x is 23.
Expressions can also be grouped together using parentheses in order to tell the
programming language which operations you want to have happen first. For instance,
look at the following code:
var x;
x = (2 + 10) * 3;
Here, 2 + 10 is evaluated first, which gives the value 12, and then 12 * 3 gets
evaluated, giving 36. This number (36) is then stored in the variable x.
You can also include functions in your expressions. For instance, we can do the
following:
var x;
x = "123"; // This is the string "123", not the number 123
var y;
y = parseInt(x) + 12;
The last line of this code combines a function call with the + operator. The function
call takes the value in x and returns its integer value, and then that value is added to 12,
yielding 135.
122
Chapter 9 Basic JavaScript Syntax
Expressions can also be contained within a function’s arguments. Take a look at the
following code:
var x;
x = parseInt("12" + "3");
Here we have "12" + "3" as an expression which yields the value "123" (because
"12" and "3" are both strings). This then gets passed into the parseInt function, which
then yields the number 123, which is then stored in x.
9.3 Control Structures
Control structures modify the flow of your program. Normally, you think of your program
as going step-by-step, one statement to the next. Control structures are syntactical units
which cause the flow of your program to be altered in some way. The two basic control
structures that every programming language has to modify that flow are conditional
branching, which causes the computer to perform either one section of code or another
based on a condition, and looping, which causes the computer to perform a section of
code repeatedly (the number of repetitions will depend on specified conditions).
9.3.1 The if Statement
The if statement is the primary way that JavaScript programmers do conditional
branching.
The if statement has the following basic form:
if (some_condition) {
// Put the code to perform if some_condition is true here
} else {
// Put the code to perform if some_condition is not true here
}
First notice the use of curly braces ({ and }). In JavaScript, curly braces are used
to group statements together into blocks. The if statement potentially has two
blocks—one to perform if the condition is true and one to perform if the condition is
false (preceded with the else keyword). You can put any number of statements inside
the blocks.
123
Chapter 9 Basic JavaScript Syntax
124
Chapter 9 Basic JavaScript Syntax
Oftentimes, conditions need to be combined. Let’s say that we want to know if both
of these are true—you are exactly 18 years old and your name is Fred. You could do
this in one of two ways. The first way is to embed one if statement inside another one,
like this:
var my_age;
var my_name;
if(my_age == 18) {
if(my_name == "Fred") {
alert("Your name is Fred and you are 18!");
}
}
Note that, first, I don’t have an else branch on these if statements. The else branch
is actually optional. If the condition is false, and there is no else branch, it will just
skip it and go on to the next statement. The other thing to note is that we can have an
if statement within a code block on a condition. In JavaScript, any code can go within
these blocks.
125
Chapter 9 Basic JavaScript Syntax
However, this takes a lot of typing. It would be nicer if we could combine the
two if statements into a single statement. We can do this by combining the boolean
expressions. Boolean expressions can be combined with two operators, && (which is
pronounced “and”) and || (which is pronounced as “or”). && yields a true value if both of
its operands are true, and || yields a true value if either of its operands are true. We can
therefore combine these statements into a single if statement using &&:
var my_age;
var my_name;
The one other boolean operator that we need to cover is the ! (pronounced “not”)
operator. The ! operator, instead of having two operands, only has one, which appears
on the right side of the operator. This operator returns the opposite of whatever boolean
value is on its right. It is also best to use the ! operator with parentheses so it is obvious
to you, to the computer, and to other people reading your code what expression you are
applying it to.
So, for instance, if I wanted to find out if the variable my_value is not between 3 and
10, I can write !(my_value >= 3 && my_value <= 10). The expression in parentheses
will yield true if the value is within range, and then the ! operator will cause it to return
the opposite.
126
Chapter 9 Basic JavaScript Syntax
The most basic looping structure in JavaScript is the while statement. The while
statement’s overall structure looks like this:
while(some_condition) {
// Perform tasks here
}
The while statement tells JavaScript to repeat the code in the given block until some_
condition is false. It checks some_condition before each time it runs the block of code,
and, if the condition is true, it runs the loop. If the condition is false, then it considers the
loop completed and moves on to the next part of the code.
Here is an example program with a while loop that will repeat until the user enters
the right value:
var answer;
while(answer != "Genesis") {
answer = prompt("What is the first book in the Bible?");
}
alert("You got the answer right!");
What this will do is start out by creating a variable called answer. Unless otherwise
specified, variables in JavaScript when they are created are given a special empty value
that is called undefined. After creating the variable, the code starts the while loop. When
it first starts, it evaluates its condition, known as the loop condition. The condition is
answer != "Genesis". This checks to see if the variable answer is different from the
character string "Genesis". Indeed, undefined is different from "Genesis", so the
condition is true. This means that we can proceed with the loop.
After the loop condition comes a block of statements wrapped in curly braces known
as the loop body. These statements are executed if the loop condition is true. Within this
loop, there is only one statement, which asks the user to answer a question and stores
the result in the answer variable. When the computer is done executing the body of the
loop, it reevaluates the loop condition again to see if we should run the loop again or if
we are done.
Let’s say that the user had erroneously answered the question by typing in “Exodus.”
What would happen? answer would have the value "Exodus". When it evaluates the loop
condition, answer != "Genesis" would still returns true. Therefore, it would run the
loop body again.
127
Chapter 9 Basic JavaScript Syntax
Now let’s say that this time they type in “Genesis” as they should. What happens
now? Well, "Genesis" gets put into answer. Now the loop body is complete again, so it
reevaluates the loop condition. This time, the condition answer != "Genesis" is false!
When the loop condition is false, it transfers control to the first instruction after the loop
body. In this case, that instruction tells the user that they entered the right value.
One thing to be careful of when writing loops is to make sure that the loop condition
can, eventually, evaluate to false. Otherwise, what will happen? It will loop forever! In
computer terms, this is known as an infinite loop. You should always double-check to
make sure that your loops will eventually terminate. We will cover infinite loops more in
the next section.
128
Chapter 9 Basic JavaScript Syntax
Next the loop condition is evaluated. Yes, num is less than or equal to 6 since its value
is 1. Next, that number is added to sum and assigned back into sum, which is now 1. The
next part is the most important part—you add 1 to num and store it back into num to move
it to the next number. The value of num is now 2. Notice that even though it is still less
than or equal to 6, it is a step closer to terminating the loop. Now we repeat the loop
condition and loop body again. At the end of the next iteration through the loop, the
value of num is, again, a step closer to terminating the loop.
After running the loop body six times, the value of num is 7, which will terminate the
loop and give the answer.
Now take a minute to think—what would happen if we accidentally left off the code
which added 1 to num at the end of the loop? num would never increase, and so it would
always be 1, and therefore num <= 6 would always be true and the loop would never,
ever finish. A loop that never finishes is known as an infinite loop. An infinite loop could
lock up your browser or, even worse, your whole computer.
When you have a simple loop like this, where there is a single variable which is
used to manage whether or not the loop repeats, that variable is called the loop control
variable. In a while loop, the loop termination condition is separated from the location
where we increment the loop control variable. In yet another location is the place where
the loop control variable gets initialized. Having these important parts of the loop in
different places can be dangerous as we can easily forget to include one or more parts of
the loop control.
However, another flow control statement is available which, for simple loops, keeps
all of the steps for managing the control variable in one spot. This statement is the for
statement.
The structure of the for statement is like this:
for(loop_control_variable_initialization; loop_condition;
loop_control_variable_modification) {
// Loop Body
}
The three places where we used the control variable are now all packaged together in
one location in the for statement. This makes the process of writing simple loops much
less error-prone. So, if we rewrite our previous program using a for statement, it looks
like Figure 9-3.
129
Chapter 9 Basic JavaScript Syntax
As you can see, everything we do with our loop control variable is contained. This
syntax allows you to better manage your loop control variables by keeping all of the
management code in one place. It also makes the code easier to read. while statements
are still very important, especially for more complicated loops with more complicated
conditions and controls. However, most of the time you can get away with using a
for loop.
9.3.4 Review
In this chapter, we covered the basics of JavaScript syntax. We have learned the
following:
130
Chapter 9 Basic JavaScript Syntax
• The two most common ways for a control structure to modify the flow
of your program are by conditional branching and looping.
• The basic structures of a loop are the loop initializers, the loop
condition, and the loop body.
• Simple loops are focused around a single loop control variable, which
is used in all three parts of the loop’s structure.
131
Chapter 9 Basic JavaScript Syntax
4. Enter the code for adding up the numbers 1 through 6 in Section
9.3.3. Be sure to create an HTML file that loads the JavaScript
code. Verify that it works.
5. Modify the code so that you ask the user what number range they
want to use for the additions. Don’t forget to use parseInt!
132
CHAPTER 10
Introducing Functions
and Scope
In the previous chapter, we learned about the nuts and bolts of how programming works,
with assignment statements, conditional branching, and loops. For small programs, this
is all you need. In fact, you can do any possible computation you might need to do with
only these features. However, as your programs get larger—even just a little bit larger—
you will need tools that will enable you to get more work done with each line of code
and to organize your code into logical blocks. Imagine, for instance, if your program was
10,000 lines long. If you needed to change a line, it might be hard to find!
Likewise, let’s say there was a task that you had to do over and over again. If you had
to type out the code for it each time, that would be a lot of wasted effort! In addition, let’s
say that you found an error (known as a bug) in your code that you had been copying.
If you had 20 copies of the code, you would have to find each copy and fix it. This is
tedious, wasteful, and error-prone.
What we need to do is to take sections of code and package them up into a unit.
Doing this will make our code both better organized and reusable. Most programming
languages use functions to organize and reuse sections of code.
133
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_10
Chapter 10 Introducing Functions and Scope
134
Chapter 10 Introducing Functions and Scope
PRACTICE QUESTIONS
2. Call the alert function a few times giving it the results of the cube_a_
number function, like we did for square_a_number.
3. The body of the square_a_number function creates a variable called
value to store the temporary result of the calculation. However, because the
calculation is so simple, we don’t really need this variable. Can you rewrite
square_a_number so that it doesn’t use a variable?
4. Change the program so that it asks the user to type in a number, then call
square_a_number to calculate the square, and then show the result to
the user.
5. Take the program you’ve just written and put the interactions with the user in a
for loop that runs three times so that it will ask the user for a number and give
the result three times.
6. Change the loop from a for loop to a while loop, and perform the operation
until the user enters a zero for the number to square.
135
Chapter 10 Introducing Functions and Scope
136
Chapter 10 Introducing Functions and Scope
make it clearer what the whole program is doing. You can look at it and say, “Oh yes, this
piece of code with the name sum_rage sums up numbers within a range. And look! Over
here we use the function with the two inputs from the user.”
Again, this is not as big of an issue with small programs, but when you write
programs with many thousands of lines of code, having the code broken up into
manageable, understandable components, each with a small, well-defined task makes
the code much easier to understand and modify.
In general, separating out the user interface from the computation is a good idea in
computer programming. This leads to a number of long-term benefits for the program
itself. Many times in computer programming, user interfaces will change regularly even
when the underlying logic stays the same. Therefore, having the core logic separated
from its interface makes it easier for the program to grow and change without causing
undue headaches. Oftentimes programs will have more than one user interface into the
logic or perhaps a user interface and an interface that is used by outside programs. Here,
separating out the core logic makes it so that this logic will not have to be repeated in
each interface. Additionally, it is a good practice to write tests to make sure your code
works. Testing core logic is usually more straightforward than testing user interfaces, so
writing the core logic separately allows it to be more easily tested.
PRACTICE QUESTIONS
1. Create a function that takes three parameters and returns the largest
of the three parameters. You will have to use several if statements to
accomplish this.
2. Create a function called multiply which will take two parameters and
perform the same function as the * (multiplication) operator. However, don’t use
the * operator in your code. Instead, perform the task by repeated adding of
the first parameter. Be sure to include code to run the function and display the
result so that you know whether you did it correctly!
137
Chapter 10 Introducing Functions and Scope
10.4 Variable Scopes
Now that we know how functions work in JavaScript, we need to talk about variable
scope. The scope of a variable refers to the locations within a program where the
variable is created, is active and available for use, and is destroyed. In some of the
earliest programming languages, all variables had global scope—meaning that the
variable always existed throughout the whole program and was accessible everywhere
within the program. However, this can quickly lead to problems. We have created
temporary variables several times already to hold intermediate values, such as the sum
variable in the sum_range function. If all of your variables have global scope, when
you call one function from another function, if both of them use the same name for a
temporary variable, then your temporary result will be overwritten by the other function!
138
Chapter 10 Introducing Functions and Scope
If all variables had global scope, the only way to avoid this situation is to make sure
that each variable had a unique name. This would be tedious and time-consuming, both
to keep track of the variable names and to write the inevitably excessively long names
that would result. Programming languages quickly adopted new scoping policies that
allowed programmers more freedom.
The type of scoping that JavaScript does for variables declared using var inside a
function is called function scope. This means that in addition to the global scope, each
function has a unique, separate scope. If we declare a variable var myvar outside of a
function, that variable exists within the global scope and is called a global variable.
Since it is global, I can access myvar from anywhere in my program. If we instead
declared var myvar from inside a function, then myvar would only be available within
that function. Such variables are often called local variables. Parameters to functions
also act as if they were local variables in the function’s scope.
139
Chapter 10 Introducing Functions and Scope
140
Chapter 10 Introducing Functions and Scope
Additionally, if there was another function that also had a locally scoped myvar, it
would be a different variable than either the globally scoped myvar or the myvar that is
locally scoped to this function. Each function’s local variables belong to that function
and cannot even be referenced outside of that function.
Having local scopes allows functions to work as “black boxes,” meaning that the
person who writes the code that calls a function doesn’t have to care about the details
of how that function is implemented. If we only had the global scope, then, before I
called a function, I would need to go and look up all of the variables it was using to make
sure I wasn’t also using the same variable. However, if a function writer only uses local
variables, then if I used that function in my program, I wouldn’t have to worry that it
might accidentally overwrite a variable I am using. This is true in larger programs even
if there is only one programmer. You will not remember the names of every variable
you use in your functions. But, if you make sure that you only use local variables and
parameters within your functions, you won’t need to remember all of the variable names
since they will all be within the scope of the given function.
Occasionally, you will need to use the global scope. In fact, this is what we are doing
on the names of the functions themselves—we are storing them in global variables. In
JavaScript, functions are stored in variables just like any other value. Therefore, in order
for functions to call each other, they must exist in the global scope. You can also define a
function inside of another function, but we will save that discussion for Chapter 14.
10.4.1 Review
In this chapter we discussed what a function is and how we can use functions in our
code. We have learned the following:
• Function parameters are positional, which means that the order that
they are defined using the function operator is the same order that
the function call must use.
• A function has a function body, which is the code that tells the
computer what to do when the function is called.
141
Chapter 10 Introducing Functions and Scope
• When repeated code sections are moved into a function, this also
makes it easier to fix bugs as they only need to be fixed in one place.
• If two functions have a local variable with the same name, these refer
to two different variables because they each exist in different scopes.
142
Chapter 10 Introducing Functions and Scope
4. Take any one of these calculators and make it so that the user can
enter as many values as they want. You can do this by either asking
the user afterward if they want to keep going or have a special
value that the user types to signal that they are done. In any case,
make it so that the user can keep using the application until they
are ready to be finished.
143
CHAPTER 11
var transaction_timestamp;
var transaction_amount;
var transaction_from_account;
var transaction_to_account;
Writing it in this way, if we had to pass these variables into a function, we would
have to pass them as four separate parameters. Imagine if we then added additional data
that went with the transaction, such as a transfer fee and the currency that the transfer
is in. The number of variables we need to move around has now gone up to 6! Not only
that, every function that touches the data would have to be rewritten to take the extra
parameters!
This is not an unusual situation. In many programs, there may be several dozen
values that all relate to each other. Passing them around as individual values can quickly
get out-of-control.
145
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_11
Chapter 11 Grouping Values Together with Objects and Arrays
Objects themselves are values and can be stored in variables and used in expressions
just like any other value.
Now, let’s look at how we assign values to objects:
JavaScript stores values in objects based on their name. These values are often called
attributes or properties of the object. So, when you type mytransaction.amount, that
tells JavaScript to look up the amount property of the mytransaction object.
This is the information we would need for a bank transaction. However, a transaction
needs information about the accounts, too. What would a bank account object look like?
Such an object would need the account number, the name of the person on the account,
and their current balance. Therefore, we might have an object that looks like this:
146
Chapter 11 Grouping Values Together with Objects and Arrays
Now let’s say that I want to define a function that processes a transaction against
an account. What I want it to do is to take my_transaction and apply it to my_account
(i.e., give the money in my_transaction to the balance in my_account). To do this, I
can create a function, which takes the two objects, picks out the values it needs, and
processes the transaction. If the account number matches the from_account of the
transaction, it removes the money from the account, and if it matches the to_account of
the transaction, it gives the money to the account. Figure 11-1 shows what this looks like.
Now I can call this function by typing process_transaction(my_account,
my_transaction);. Notice that we didn’t have to pass in every value; we only had to
pass in the objects which contained the values we needed.
Another important point is that when we passed in objects, we could actually modify
the object that we were receiving. Note that this function doesn’t return a value. Instead,
the function modifies the account object itself. The result is the modification of the
object, not the return value. This is known as a mutating function because it modifies
(i.e., mutates) the objects passed as parameters rather than return a value. Mutating,
however, only works with objects. Basic values (i.e., numbers, strings, etc.) passed
directly as parameters cannot be modified like this.
Note that if a function doesn’t have a return value, it returns the special value
undefined, which means “no value.”
In any case, objects allow functions to manipulate values, not just process them.
When we were just passing in numbers and strings, even if we modified the parameter
variable, it wouldn’t modify the value in the sending function. Now that we are using
objects, we can modify the properties of any object passed in. However, we cannot
replace the whole object with a new one, though we can modify all of its properties.
147
Chapter 11 Grouping Values Together with Objects and Arrays
PRACTICE QUESTIONS
1. Find a product catalog (of any kind). Look through the catalog. List out the data
fields that it has for each catalog item. Pick out two catalog items to use for the
rest of this practice.
2. Create a program that builds two objects—one for each item you picked out.
It should use the fields you listed in the previous step (feel free to skip fields
if they are complex fields, such as an image). Use an alert function to show
some of the pieces of data you have put in your objects.
3. Create a function that displays all of the information about a single item that
takes one parameter—the item to display. It should display each property
defined on that object. Then call that function for each item.
4. Create a function that asks the user for the values to be placed in that object
and then returns a new object with those values assigned to properties on
that object.
148
Chapter 11 Grouping Values Together with Objects and Arrays
However, {} has a few more tricks available as well. You can actually use it to specify
a set of starting attributes at the beginning, so you don’t have to assign them one-by-one.
The syntax looks like this:
var my_transaction = {
timestamp: "2014-02-05",
amount: 1000,
from_account: "12345",
to_account: "54321"
};
As you can see, with this syntax, in between the { and }, there are sets of named
values that will be our object properties. Each property name is followed by a colon
and the value of the property we are trying to set. This makes initializing objects much
faster and cleaner than the long way. Keep in mind that the names of properties should
generally be limited to the same types of names that are allowed for variables (i.e., don’t
put spaces, dashes, or special characters in the property names).
PRACTICE QUESTIONS
Modify the practice work of the previous section to use the shorter object creation syntax.
149
Chapter 11 Grouping Values Together with Objects and Arrays
var children_ages = {
first_child: 11,
second_child: 8,
third_child: 7
};
That somewhat works, but it would be hard to use such a structure. For instance, if I
wanted to write out each of their ages, it would be hard to write a loop to go through each
child and write out their ages, especially if I didn’t know how many children there were
ahead of time.
An array, on the other hand, allows us to define ordered sequences of values. So,
instead of our awkward object, we could write something more elegant like this:
In this code, children_ages is first assigned a blank array—that’s what new Array()
does. The first line tells JavaScript to make an empty sequence of values and store it in
the variable children_ages. In the next line, we tell JavaScript that the first value in the
sequence should be 11. The [] notation says that we need to use the number inside
the brackets to tell us which element of the array we are referring to and, if it doesn’t
150
Chapter 11 Grouping Values Together with Objects and Arrays
exist yet, to create it.1 Elements in an array are referred to by their index number. Index
numbers start at zero (not one) and go up from there.2 Therefore, [0] says to refer to the
first member of the array.
The code children_ages[0] = 11; tells JavaScript to look in the children_ages
array and try to find the first value, and it will create one if it doesn’t already exist. Next, it
will look at the right-hand side of the equal sign and see what the value of the expression
is. In this case, the value is 11 so it stores the number 11 at index 0 of children_ages.
The same thing happens with index 1 and 2. At the end of the code, there are three
values in children_ages—11, 8, and 7.
1
Note that, in many programming languages, it is an error to assign to an array index without the
variable being set up to hold at least that many values ahead-of-time. JavaScript handles it just
fine, however. JavaScript knows that if the array member doesn’t exist, it should create it.
2
In ordinary life, we are used to labeling sequences of values starting with a 1, but computers
usually label sequences of values starting with a 0. This is known as zero-based indexing. The
reason for this is that, at least historically, the index was actually the offset from the start of the
array. Since the first element is the start of the array, the first element isn’t offset at all from the
start of the array, so its index/offset is zero.
151
Chapter 11 Grouping Values Together with Objects and Arrays
An array has a few special properties that can be used to find out information about
the array. The most important property that an array has is the length property. The
length property returns the number of values that the array holds. So, in our code,
children_ages.length would yield 3 since it holds three values. Notice that, since
JavaScript arrays use zero-based indexing, this is one more than the largest index, which
is 2. The fact that the size of an array is one larger than the largest index is a quirk of
computer programming that you will frequently have to keep in mind.
Figure 11-2 shows a function that takes an array of ages and returns the largest one.
In this code, the for loop repeated using i as the loop counter. i starts at zero since
the array indexes start at zero. At the end of every loop, i increases by 1 (i++ is just a
short way of writing i = i + 1). Incrementing the index by 1 basically means “go to the
next value in the list.” The middle part of the for statement is the condition. Here, the
condition is i < age_array.length. Since the array length is one greater than the last
index of the array, this condition says to keep going as long as we have a valid index for
the array. When i finally makes it to age_array.length, it will no longer point to a valid
value, so we should stop looping.
What do we do inside the loop? We are simply testing each value (age_array[i])
to see if it is greater than the previous value (the_largest). If it is greater, we write
the current value into the_largest. Otherwise, we ignore it. Then, after the loop has
completed, we return the value of the_largest for the result of the function.
Figure 11-3 shows how this function can be incorporated into a larger program.
152
Chapter 11 Grouping Values Together with Objects and Arrays
Just like we were able to simplify object creation with the {} syntax, arrays have
a special syntax, too, which makes them easy to create. In JavaScript, you can create
an array just by putting in a list of numbers in square brackets ([]). Here are some
examples:
153
Chapter 11 Grouping Values Together with Objects and Arrays
If you need to access the last element of the my_array array, you can do it with
my_array[my_array.length - 1]. The first element is always my_array[0]. Also, if you
want to get rid of elements at the end of the array, you can also set the length property.
To get rid of all elements of the array my_array, just do my_array.length = 0;.
PRACTICE QUESTIONS
1. Type out the entire largest_age function. Test it by sending it different arrays
and making sure it always returns the largest age.
2. Instead of creating the array values yourself, have the user type the values.
For the first time around, have the user type in exactly three values. Make sure
these values get converted to numbers before storing them in the array!
3. Extend your program so that the user can type in as many values as they want.
Remember to include a way that the user can indicate that they are finished
either by asking them if they are done after each one or asking the user to type
a special sentinel value that indicates that they are done.
154
Chapter 11 Grouping Values Together with Objects and Arrays
As you can see, we start out with a blank object in the variable my_record. We then
add a name to the object. Next, we add an empty array to the object, and we name the
property children. Now, to access this array, we have to use my_record.children.
Since my_record.children is an array, we can use indexes on it. Therefore, my_record.
children[0] refers to the first value in the my_record.children array. Since that index
doesn’t exist yet, it gets created. But what is stored there? It’s a new, blank object!
Therefore, my_record.children[0] now refers to an empty object. What can we do with
objects? We can add properties. We can create a name property on this new, empty object
by doing my_record.children[0].name = "Jim";. We then set the age in the same way.
At the end of this process, we have an object that has an array of objects.
Now, if we wanted to use our largest_age function, we would have to rewrite it.
Why? Because now the array is no longer an array of numbers but of objects. Therefore,
for each object, we would have to look for the age property. Figure 11-5 shows the code.
What we did in this function is modify our loop so that it stores the object
temporarily in a variable called child. We then use child.age to access the child’s age.
Note that instead of using this extra child variable, we could have just done it directly
by typing in child_array[i].age, but creating the extra variable makes for much less
typing and much easier reading in the long run.
155
Chapter 11 Grouping Values Together with Objects and Arrays
To call this function on our list of children from my_record, we would simply write
largest_age(my_record.children).
Figure 11-4 showed the long way to build a complex object. However, just as there is
an easier way to write simple objects and arrays, complex objects and arrays can also be
built using the simplified syntax. Figure 11-6 shows the exact same object that we built in
Figure 11-4, written using the simplified notation.
As you can see, this takes much less typing and is much easier to read. It takes up
more space because of how it is written, but you don’t have to do it that way—JavaScript
does not care how much or little space is used. You could write that whole complex
object on one line if you wanted to, but I think the clarity that comes from having things
separated out is worth the extra space it can take up.
11.6 Object Methods
A method is a function which is physically attached to an object. The functions we have
seen so far (such as alert and prompt) are stored in global variables that are available
anywhere. A method is a function that is stored as a property on the object itself.
Remember, creating functions is actually a two-step process—the function keyword
creates the function, but then we have to assign it to a variable in order to call it by a
name. However, just as we can store a function in a variable, we can also store it in an
object’s property. Functions stored in this way are called methods.
156
Chapter 11 Grouping Values Together with Objects and Arrays
Since they are stored in object properties, they don’t have a global name; they are
only accessible through the object. Additionally, methods implicitly pass the object that
they are a property of when they are called.
As an example, let’s look at a built-in method of array objects, known as push. The
push method simply adds an item to the end of an array. The following code creates the
array [5, 6, 7]:
What my_array.push(5) does is look at the push attribute on the my_array object
and call the function that it finds there. Because it is called in this manner, it implicitly
passes my_array to the function and explicitly passes the number 5 as the first parameter.
The push method then accomplishes the equivalent feature of writing my_array[my_
array.length] = 5;.
157
Chapter 11 Grouping Values Together with Objects and Arrays
Object methods allow for a number of benefits. First of all, they reduce the number
of globally defined methods. Just like we generally try to eliminate global variables
because it takes mental space to remember which ones are already in use, packaging
functions into methods on objects instead of into global variables reduces the number of
globally defined methods we need to care about.
Similarly, because the methods are defined on the objects themselves, we can
actually reuse the same method name on different objects. On arrays, push means “push
the value onto the end.” However, push may mean something entirely different for other
types of objects (like a lawnmower). Therefore, on a different object, there may be a
push method that means something else entirely. If all of these different functions had to
exist on the global scope, they would all need different names, such as array_push and
lawnmower_push. This takes more typing and winds up actually being more confusing.
Finally, the method syntax makes it clear who the primary player is in the method.
The object that the method is defined on is usually the most important parameter in the
method and provides the context for the action. It makes code read somewhat similar to
a sentence. You can read my_array.push(5) as saying, “tell my_array to push the number
5.” At least to me, this is clearer (or at least cleaner) than if the syntax would be array_
push(my_array, 5).
The mirror image of the push method on arrays is the pop method. The pop method
removes the last element of the array (decreasing its length by 1) and returns the value
that was removed.
We will dive deeper into methods (and how to create your own methods) in
Chapter 15. However, for now, I just want you to be familiar with how they operate, as
we will be using them more in Chapter 12.
PRACTICE QUESTIONS
1. Write a program so that a user can continually add items to an array until they
are done. Add them using the push method. Then, when finished, add up all the
values in the array and show the result.
2. See if you can create an object and assign a function to one of its properties.
You won’t know how to receive the implicitly passed object until Chapter 15,
but you can at least practice assigning and using functions as object properties.
158
Chapter 11 Grouping Values Together with Objects and Arrays
11.6.1 Review
In this chapter, we covered the basics of composite values—objects and arrays. We have
learned the following:
• Array indexes are zero-based, which means that the first index
is always 0 and the last index is always 1 less than the length of
the array.
• Each array has a length property which tells you how large the
array is.
159
Chapter 11 Grouping Values Together with Objects and Arrays
160
CHAPTER 12
Interacting with Web
Pages
In previous chapters, we have learned how objects work and how to build our own
objects. However, JavaScript also comes with several existing, built-in objects for you to
use. These standard objects are the gateway between your program and the rest of the
system, including the HTML document, the screen, computer storage, communication
facilities, and other important system features. In this chapter, we are going to use the
standard document object to interact with the web page.
Note that for the first part of the chapter, we will only be interacting with the
JavaScript console. Extra steps are needed to make this work with a script that is loaded
from a web page, which will be covered in Section 12.6.
161
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_12
Chapter 12 Interacting with Web Pages
Now that you have your web page loaded, open up the JavaScript console as described
in Appendix B.4.1. Now, just to get used to how the console works, enter 2 + 5 into the
console and hit enter. What happened? It should have given 7 as the result. After each
command, when you hit the enter key, the console gives you the value of what you typed.
Now type in var a = 2 + 5; and hit enter. What happened this time? It should give
back undefined. Why is this? The value 7 got loaded into the variable a, but the result of
the variable declaration is nothing. So, don’t be surprised if, after declaring a variable,
the result is undefined. That is normal.
To make sure that a received our value, just type a into a line by itself. It should return
the value 7, which means it knows the value of a. Now we are going to intentionally make
a mistake. Type into your console a = 7 +; and hit enter. It should give you back some
sort of error, such as “syntax error” or a similar error message. This is important to pay
attention to. If you are using the console, and you get an error message, pay attention to
it because you probably entered something wrong somewhere. Recheck what you typed
to make sure it is valid. Programming languages tend to be very picky. A miscapitalized
word, an accidental space, or a misplaced semicolon will prevent your code from
working.
162
Chapter 12 Interacting with Web Pages
PRACTICE QUESTIONS
Before moving on to manipulating the web page, you should practice with the JavaScript
console.
3. Enter the square_a_number function from Chapter 10. Because the console
processes each line as you type it, you will need to put the whole function on
one line.
4. Now use square_a_number to find the squares of 3 and 6 in the JavaScript
console.
document.getElementById("first_paragraph");
163
Chapter 12 Interacting with Web Pages
This will yield an object that represents the HTML element of the first paragraph.
Once we have this object, we can make modifications to it that will be reflected in the
web page itself. Each browser will display this value differently in the console, but the
underlying result is the same—it is a JavaScript object that represents the HTML element
we see on the screen. In any case, we don’t just want to display the value, we want to
manipulate it. A good first step is to store the object in a variable. Therefore, do the
following:
var x = document.getElementById("first_paragraph");
Now the object representing the HTML element is stored in our variable x. What can
we do with it? One simple thing you can do is to change out the text. HTML elements
that only have text in them (i.e., they have no child elements) can have that text accessed
or changed through their textContent property. Type out the following:
x.textContent
It should give back the value "This is my first paragraph", though possibly with
some extra spaces. So, now that we can access the textContent property, we can also
change it. Type the following to put new text on your paragraph:
You should see your web page instantly change with the new paragraph text.
As you can see, if we attach the id attribute to our HTML elements, we can easily find
them and manipulate them in our JavaScript programs.
PRACTICE QUESTIONS
3. Use the prompt function to ask the user for a string and store that in a variable.
Now set the text of the paragraph to that value.
164
Chapter 12 Interacting with Web Pages
This creates a new element but doesn’t add it to the page. It is merely floating in
memory, only existing in the variable. We haven’t told the document where we want it to
go. We now want to put our new element as the last thing in the <body> element. So, first,
we need to look up the body element:
Now we need to tell the body element to append our new element to the end of its
child elements. This is done using the appendChild method of our body element. Type
the following:
body_element.appendChild(new_element);
PRACTICE ACTIVITY
To practice adding HTML content to web pages, we are going to create an <ul> tag and then,
through the JavaScript console, add additional <li> tags to it. If you get confused on any step
in here, go back through the previous sections to find out how to do each step.
1. Start out by altering the HTML file used in this section to add a <ul> tag in it
with at least one <li> tag in it.
2. Give the <ul> tag an id attribute so you can find it with JavaScript in the
next step.
165
Chapter 12 Interacting with Web Pages
4. Now use the createElement method from document to create a new <li>
tag to put in it.
5. Now use the textContent property on the new tag to set it to whatever text
you want.
6. Now use the appendChild method on your <ul> element to add the new
<li> tag to the end of your list.
8. See if you can create a brand new <ul> tag with JavaScript and add it to the
bottom of the page. Then add additional <li> tags to your JavaScript-created
<ul> tag.
166
Chapter 12 Interacting with Web Pages
Now, open the JavaScript console. The first thing we need to do is look up the two
<input /> elements and store them into variables. To do this, enter in the following:
Now type fld1 on a line by itself to make sure that it gives back an HTML element as
a value. If it doesn’t, you mistyped something. Do the same to check fld2.
Now type in the following:
fld1.value = "Hello";
167
Chapter 12 Interacting with Web Pages
As soon as you type this, the text “Hello” should appear in the first field. Go into the
second field and type in the text “Goodbye” into the web page. Now type this into the
JavaScript console:
fld2.value
It should now print onto the console the value that you typed ("Goodbye" if you
followed directions). Now we know how to set and read values from <input /> elements!
Now look up the <span> tag. Remember, the <span> tag is used for specifying a
region of text. In our case, we are specifying the location where we want to write the
result. In any case, do the following to look up the <span> tag, so we are ready to write to
that location in the page:
Now type in results_span on a line by itself so that you can see if you correctly
retrieved the <span> element.
What we are going to do is read a number from each input field, multiply them
together, and write the result into the <span> element.
Start out by typing in two numbers, one in each input field. For this example, let’s
assume that you type in “5” in the first field and “7” in the second field. Now, remember,
since this is typed from the keyboard, it is treated as a string, not a number. Therefore,
fld1.value will be the string "5" not the number 5 and fld2.value will be the string "7"
and not the number 7. What we need to do, then, is use our parseInt function to convert
these strings into numbers.
Type the following in the JavaScript console to read the values of the fields and store
them into variables:
Now, val1 and val2 should have the numbers that you entered in them. You can
verify this by typing the variable name in the console on a line by itself and making sure
it gives you back the correct value.
Now, we need to multiply the two numbers together. Type in the following to
accomplish this:
168
Chapter 12 Interacting with Web Pages
results_span.textContent = result;
PRACTICE ACTIVITY
Practice your skills by using the JavaScript console to change the text of the final paragraph in
the HTML file to the value typed into one of the <input /> elements.
So, to start with, we are going to create a function that performs the tasks that we
did in the previous section. For readability, I am going to write it out in several lines.
However, because the JavaScript console interprets one line at a time, you must type out
the whole function on a single line. Don’t worry, the JavaScript language works exactly
169
Chapter 12 Interacting with Web Pages
the same whether it is one line or many—that is why it uses the semicolon to separate
statements. So, as long as you type everything correctly, it will work just fine on one line.
Figure 12-3 shows the function.
Notice that it uses the document object. This works because document is a global
variable. Also note that the function takes no parameters. It simply works by using the
document global variable.
Once you have typed the function (all in one line) into the console, calling the
function should perform all of the tasks. To test it out, put two different numbers in the
input fields, and then, in the JavaScript console, write the following:
multiply_fields();
This should multiply the two numbers and write the result in the results <span>
tag. If it did not work, recheck your function.
Now, we want this function to run whenever a user clicks on our button. This is
actually very easy to do. <button> tags have a property called onclick. If you set onclick
to a function, it will call that function whenever it is clicked! For right now, you should
only use functions that take no parameters.
So, to get this set, we need to look up the <button> on the page and then set its
onclick property. Here is the code:
Note that we are not calling the function multiply_fields here. We are storing the
function itself in the onclick property for later use. Remember, JavaScript functions are
themselves values and are stored in variables and properties just like any other value.
Therefore, we are storing the function in the btn object, and the btn object will call the
function when it is time.
To try it out, put in two values and click the button. If everything was set up right, it
should display the results in the proper place.
170
Chapter 12 Interacting with Web Pages
Now, after you have added your <script> tag to the HTML file and have saved
everything, reload your page. After you type in two numbers and hit the button, it should
give you your answer.
171
Chapter 12 Interacting with Web Pages
PRACTICE ACTIVITY
Now that you know how to add functionality to a web page, this activity will have you add a
second function to the same page.
2. Next, create a new function in your JavaScript file that will add the two
numbers rather than multiply them. Call the function add_fields. Do not
remove the existing multiply_fields code. Just add a new function.
3. Now add a second button to the page. Be sure to give it a distinct id attribute
so you can find it. Do not remove the existing button.
4. Now add code to your JavaScript file so that it will find the new button and
attach your add_fields function to the button.
5. Test out your new page. Be sure that both buttons do the appropriate
operations.
12.7 Logging to the Console
If your program has actual errors, those are generally reported in the JavaScript console.
Therefore, when doing development, I almost always have the console open so I can see
where I screwed up.
However, you can also write values to the console yourself. This is often helpful if
you have complicated code or calculations and want to keep track of the status of the
computations as you go along. JavaScript helpfully has a global variable called console
which allows you write to your console. The console object has a log method which
allows you to write whatever you want to the console.
Modify your previous program to add in the following line somewhere in you
multiply_fields function:
console.log("I am here");
Now, when you click the button, it should write “I am here” to your console.
Most browsers have additional tools for debugging your JavaScript programs. The
details of how to use these are beyond the scope of the book, but I’ll at least mention the
172
Chapter 12 Interacting with Web Pages
most common and most powerful one—breakpoints. A breakpoint tells the JavaScript
interpreter to stop at a certain line of code. Then, you, the programmer, can look at the
values of all the variables at that point and step JavaScript through your code one line at
a time to see how each line affects what is happening.
Console logging and breakpoints are often used as substitutes for each other, but
they each have areas where they are more suited to the problem than the other. Console
logs are useful for monitoring running programs in real time. By having console logs
report important status information, you can watch your program as it goes through
computations. Breakpoints are good when you have a specific location in your code
that is failing and need to see how every step in the process affects the results. Why is
this variable being set to that value? Which condition is causing this to take the wrong
branch? Which value is unexpectedly null or undefined? These questions are quickly
answered by setting appropriate breakpoints and walking through your program.
This chapter introduced you to the Document Object Model (DOM). You may wonder how you
know what objects, properties, and functions are available to you. It might seem mysterious
or even arbitrary that if you stick a function in the onclick property, it magically calls that
function when a button is clicked. When programmers create systems such as JavaScript and
the DOM, they have to make choices about how things are represented and interacted with—
what the objects and properties are called and how they are used. The names of these objects,
functions, and properties are essentially arbitrary—they are whatever the programmer
decided to name them. Hopefully the names make sense and can help you learn how to use
them, but sometimes, either through sloppiness or history, things wind up with weird names
that don’t make sense. This is fairly normal in programming.
The list of standard objects, properties, and functions that a system supports is called its
Application Programming Interface or, more commonly, its API. How do you know what
objects, properties, and functions are available in an API? Usually, this is done by programmers
writing them down and sharing them through documentation. Most programming systems
have a reference which lists all of the available functions. However, these are usually pretty
lengthy since system developers try to think of all of the things that you might want to do and
provide functions for each of them. Usually, though, most APIs are focused around just a few
concepts, and once you learn those, the rest are details that you can look up later.
173
Chapter 12 Interacting with Web Pages
12.7.1 Review
In this chapter, we practiced interacting with web pages using JavaScript. We have
learned the following:
• The document object is the gateway that allows us to interact with the
current web page.
• The DOM is the list of objects and properties that can be used when
interacting with an HTML page and its elements.
• The id attribute of an HTML tag can be used to find the element from
JavaScript for manipulation.
• The <input /> tag can be used to allow a user to enter in data for
processing.
• The value property of the <input /> tag’s object can be used for
reading or setting the value of the text field.
• The <button> tag can be used to initiate processing. Be sure to set the
type="button" property so it will work correctly.
• Setting a <button> element object’s onclick value to a function will
cause that function to run when the button is clicked.
174
Chapter 12 Interacting with Web Pages
2. Create an HTML page that just has an empty <body> tag with just
an id attribute. Write JavaScript to build a page with a heading,
a paragraph, and a <ul> list with two items in it using only
JavaScript code.
3. Create an HTML page that has an empty <ul> tag with just an
id attribute. Write JavaScript that uses an array and a for loop
to populate the <ul> element with <li> elements. Use the array
["One", "Two", "Three"] and have your code loop through each
element of the array to add a new <li> element for each member
of the array.
175
PART IV
Intermediate JavaScript
This part dives deeper into the mechanics of the JavaScript language. This will require
you to think deeper about the internals of how JavaScript interprets what you write and
what is actually happening on the computer when you write code.
CHAPTER 13
Recursive Functions
and the Stack
In Chapter 10, you learned that functions can be used to package together pieces of code
into well-defined units that can be reused over and over again. In this chapter, we are
going to go into more detail about how JavaScript keeps track of these functions.
179
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_13
Chapter 13 Recursive Functions and the Stack
the programming language keeps track of what is currently going on in the program. It
is, quite literally, a stack of information that the programming language is keeping about
what is happening in the program.
For instance, when a program calls a function, it has to remember where to return
to after the function completes. Therefore, it pushes the return location onto the stack,
so it remembers where to go after the function is finished. If that function calls another
function, then it pushes another return location onto the top of the stack. When the
second function finishes, it looks at the top of the stack to see where it should return
to, pops (removes) the value, and resumes operation at the point indicated. When the
original function finishes, its return location is now back at the top of the stack, so it
knows where it should return to.
Figure 13-1 shows some functions that call each other. It includes comments
showing different locations that the program will be executing (marked as “position 1,”
“position 2,” etc.) so that we can discuss the flow of the program through the functions.
If you skip the declaration of the variables for the functions, the actual code starts
at position 8. For our purposes, we can conceive of the stack being empty when the
program starts running.
The first thing the program does is call the function function_one. When function_
one ends, where should the program continue? It should continue running at position 9.
The stack looks like Figure 13-2.
Now, look at function_one. The code starts running at position 1, and there is an
immediate function call to function_two. Think about where the code should continue
running after function_two finishes—it should continue running at position 2. Therefore,
that position is pushed to the top of the stack. The stack now looks like Figure 13-3.
Now, what does function_two do? It calls yet another function, function_three.
Since the next place it should start executing after function_three finishes is position 5,
that is now pushed onto the stack. The stack now looks like Figure 13-4.
Now, function_three makes its own function call, but this time to a built-in function.
Function calls to built-in functions work exactly like other function calls. So, where should
function_three resume after alert finishes? It should go back to position 7, and the
stack will look like Figure 13-5.
Now things get interesting. What happens when alert finishes? How does it know
where to go? It just looks at the top of the stack! The top of the stack says, “When you are
done, return to position 7 in the code.” JavaScript then removes the top of the stack and
180
Chapter 13 Recursive Functions and the Stack
continues operation at position 7. Now the stack looks like it did in Figure 13-4. But then,
the only thing left to do at position 7 is to return from the function. Therefore, it performs
the procedure again—it looks at the top of the stack to see where it should return to.
Now it says to return to position 5, and the stack is back the way it looked in Figure 13-3.
Again, the only thing to do in position 5 is to return, and the stack says to return to
position 2. We therefore return to position 2 and remove it from the top of the stack. The
stack is then back to looking how it did in Figure 13-2.
181
Chapter 13 Recursive Functions and the Stack
Oftentimes, what happens in code is more complicated than this. Since many of our
functions have return values, and the functions are actually only part of the statement,
the return must send the program to the correct place in the middle of the line of code.
182
Chapter 13 Recursive Functions and the Stack
This is the same idea as before, only that the positions that the computer keeps track of
are more complicated than just line numbers like we had for the example. For instance,
take the following code:
In this case, we are calling a function several times in the same line, and each one
returns to a different place in the line. Don’t worry. JavaScript knows exactly where
to return to each time. Its positioning system is much more exact than our crude
examples above.
Also, as we will see going forward, JavaScript stores much more information in the
stack than just the return location.
183
Chapter 13 Recursive Functions and the Stack
So, when we call sum_range, the stack looks a little more complicated. Figure 13-8
shows how the stack looks when the sum_range function is underway when it first begins
its for loop.
Note that there is a big black line around the current scope and the current location.
That is known as the stack frame. The stack frame is all of the data that is packaged
together on the stack for a specific function call. The scope and the return location go
together for each function call, and together they make up a stack frame.
The stack frame points JavaScript to the scope that is currently being used to process
variables. The way that the scope works is that when you refer to a variable, say x, in
your program, JavaScript first looks on the stack to see where your current scope is. It
then looks for that variable in the current scope. If it finds it, that is what it uses for the
variable. Do you see the box at the top of the local scope that says “Parent Scope”? Each
scope links to a parent scope, which tells JavaScript where to look for variables if they are
not in the current scope. In this case, the parent scope is the global scope. In Chapter 14,
we will see how we can chain together even more scopes.
So, when a function is called, not only is the return location put onto the stack, but a
brand new scope is created, and a link to this new scope is also placed on the stack.
Let’s look at another, similar program which will declare a function called sum_
squares_of_range. This works just like sum_range, except that it will square each of the
numbers in the range. The code for this can be found in the following:
184
Chapter 13 Recursive Functions and the Stack
185
Chapter 13 Recursive Functions and the Stack
In this program, the stack gets two levels deep. First, it calls sum_squares_of_range.
This leads to a situation similar to the previous example. Then, to calculate the square
of each number, it calls square_number on each of them. Figure 13-10 shows the stack
layout after the first call to square_number just before it returns. Notice that all of the
local variables exist for both functions, but they are only reachable from within their own
functions. When the square_number function is active, the “current scope” points to the
local scope for square_number, which has its variables plus a link to the global scope.
Therefore, when square_number sets the value of x, it only affects its own value for x.
The x from sum_squares_of_range is not even visible to this function. Therefore, even
though we are assigning a value for x, it is only for the local copy of x that is specific to
this function. When the function returns, it will remove both the link to the local scope
and return location. When sum_squares_of_range starts executing again, its own scope
will be at the top of the stack, and it won’t see the scope of square_number at all.
One additional thing to note is that when a function first starts executing, the local
scope only has entries for the parent scope and the parameters. JavaScript relies on the
var keyword to create new variables in its scope. The var keyword causes JavaScript to
look in the current scope (and not any parent scope) to see if the variable exists in that
scope. If the variable does not exist, JavaScript creates the variable in the current scope. If
the variable already exists, JavaScript does not create a new copy but keeps using the one
that is already there.
186
Chapter 13 Recursive Functions and the Stack
187
Chapter 13 Recursive Functions and the Stack
PRACTICE ACTIVITY
1. Look at the programs you wrote in Chapter 10 that use functions. Pick one
of them.
2. Print out your function. Draw lines from any function call to the beginning of
the function that is being called. Draw lines from the return statements to the
place in your program where the program returns.
3. Create a diagram for this program of the stack, local scope(s), and global scope,
similar to the one in Figure 13-10, for when at least one function is active.
13.3 Recursive Functions
Now that we know how stack frames and local variables work, it is time to learn about
recursive functions. A recursive function is a function that is defined in terms of itself.
Think about the program back in Figure 13-7 that summed all of the values between two
numbers. In the program, we used a loop to go from one side of the range to the other.
But is there another way to think about that problem? Another way to pursue it?
Think about summing all of the numbers from 4 to 10. Is there a smaller, similar
problem that works the same way that we might be able to use? Indeed, summing all of
the numbers from 4 to 10 is the same thing as adding 4 to the sum of the numbers from
5 to 10. So, sum_range(4, 10) gives us the same answer as 4 + sum_range(5, 10).
Likewise, sum_range(5, 10) gives us the same answer as 5 + sum_range(6, 10).
Defining a function in terms of itself is called a recursion. How might we write a
program that uses recursion? Figure 13-11 shows a partial implementation of what that
might look like.
188
Chapter 13 Recursive Functions and the Stack
As you can see, the function is defined in terms of itself. However, one problem
you would realize if you tried this function is that it never stops! There is nothing in
the function that makes it stop when it gets to the end of the range so it will just keep
on going.
When writing recursive programs, there are two main situations to code for—the
base case and the inductive case. The inductive case is the one we have already
written—it is the case that uses recursion to solve the problem. The inductive case gets
its name from inductive proofs in mathematics, which are very similar to recursive
functions. The case we are missing is the base case—it is the case that stops the recursion
to return an answer. In our program, the base case happens when r_start and r_end
are equal. When this happens, we don’t need to recurse anymore—we know what the
answer is! When the start and end of the range are equal, we just return that number.
Therefore, the full definition of our sum_range function using recursion looks like
Figure 13-12.
As you can see, there is now an if statement that checks for the base case and
immediately computes the answer if it is found. Otherwise, it proceeds recursively.
However, you might have noticed something funny. Here we are using local
variables, but we are using the same local variables over and over. Wouldn’t these
variables get clobbered each time we call the function? As a matter of fact, they don’t.
The reason for this is that JavaScript creates a new local variable scope every time the
function is called. Therefore, each time that sum_range is called, there is a new local
scope created. So, if you call sum_range(2, 5), it will create four local variable scopes,
one for each time sum_range is called.
After the third call, the stack would look like Figure 13-13. Notice how, after the
third call to sum_range, there are exactly three copies of the sum_range local scope in the
drawing, each of them with the global scope as a parent scope and, with it, their own
values for r_start and r_end. This is how the computer makes recursive function calls
possible.
189
Chapter 13 Recursive Functions and the Stack
In the example so far, there wasn’t a reason to use recursion. In fact, with all of the
function calls, stack frames, and local scopes generated, our code was actually much
slower than when it used a simple loop. Nonetheless, there are many times when
recursion is the way that makes the most sense or it is the easiest to write a program
for. Programs today rarely need a lot of optimization. While the speed of the program
itself shouldn’t be discounted, what usually counts the most is the amount of time the
programmer takes to write the program or the amount of time another programmer
takes to read and understand a program. Those are usually more important than raw
computing speed.
Knowing recursion will help you see the solutions to some problems more easily.
When you become comfortable with recursion, you begin to see many complicated
problems as merely simple problems in disguise. Additionally, knowing recursion will
help you better understand other people’s code when they use recursion. The best time
to use recursion is when you can envision the problem as being the same problem over
and over again, with each step just being a smaller version of the previous problem.
190
Chapter 13 Recursive Functions and the Stack
191
Chapter 13 Recursive Functions and the Stack
13.3.1 Review
In this chapter, we learned how the JavaScript stack worked and how it enables us to
write recursive functions. We have learned the following:
• This stack system allows JavaScript to return to the right spot in your
code even if a function is called from more than one location.
• JavaScript keeps a separate list of local variables (the local scope) for
every time a function is called even if it is the same function called
more than once.
• Each JavaScript scope has a link to a parent scope. If the variable you
reference cannot be found in the local scope, it tries to look it up in
the parent scope.
192
Chapter 13 Recursive Functions and the Stack
• Recursive functions are best used when each step of a problem is just
a reduced form of the larger problem.
3. Print out your factorial function. Circle the inductive case and the
base case.
193
CHAPTER 14
Manipulating Functions
and Scopes
In Chapter 10, we learned about functions and how they create local scopes. Chapter 13
went into further depth about how the JavaScript program stack helps JavaScript keep
track of where it is in the program and what local scope to use. In this chapter, we are
going to go deeper and show how functions can be passed as parameters and returned
as values and how to generate new functions that inherit from a different scope than the
global scope.
195
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_14
Chapter 14 Manipulating Functions and Scopes
196
Chapter 14 Manipulating Functions and Scopes
The code for that is shown in Figure 14-2. As you can see, the only difference
between sum_squares_of_range and sum_cubes_of_range is that square_number is
replaced by cube_number in the new code. Wouldn’t it be nice if we could have just one
function for both of them and then just send up whichever function (we’ll call it the
transformation function) that we want to apply to each number? Well, in fact, you can
do just that. What we can do is create a parameter to be used for the transformation
function.
The new code looks like Figure 14-3. As you can see, this is still the exact same code;
the only difference is that square_number is replaced with transformation, which is
passed in as a parameter! These types of functions, whose functions are modified by
other functions passed in as parameters, are called higher-order functions.
197
Chapter 14 Manipulating Functions and Scopes
PRACTICE QUESTIONS
1. Modify the program in Figure 14-3 so that you add a function that raises
the number to the fourth power and then pass it into sum_range_with_
transformation.
2. Modify the program again so that it simply sums the numbers from 3 to 6
without any transformation. (Hint—create a function that just returns the
number given.)
198
Chapter 14 Manipulating Functions and Scopes
Let’s start by looking at a way that does not work. Take a moment to see if you can
figure out what is wrong with the program shown in Figure 14-5. If you haven’t figured it
out yet, try putting it into a web page and running it. What happens?
The problem with the program is that the definition of counter is a local variable.
Therefore, every time the function is run, it will create a brand new variable named
counter and set it to zero. Because of this, this function will always return the value 1.
One way around this is to make the counter variable into a global variable instead
of a local one. The code in Figure 14-6 will work a little better. This one actually behaves
the way we want it to, but it has two very large drawbacks. The first drawback is that the
counter variable is a global variable. This means that the person using the next_value
function has to know about the counter variable so they don’t use it themselves. It is bad
programming practice for the user of a function to have to know so much about how a
function is implemented. The second drawback is that this only allows for one counter
function in the program. In order to get a second counter function, we would need to
recode it. It seems very wasteful to write the exact same code twice, only changing the
variable names.
In order to solve these problems, we need a way to make the scope of counter
isolated from the global scope and to be able to create new instances of the counter
function on the fly with each having their own independent counter variable. Both of
these can be solved by making function-generating-functions.
199
Chapter 14 Manipulating Functions and Scopes
200
Chapter 14 Manipulating Functions and Scopes
In Chapter 10, we learned that the function operator creates a new function with
the given code. In Chapter 13, we learned that each time the function is called, a new
local scope is created for that function. We also looked at how each new local scope has
a link to a parent scope, which, so far, has been the global scope. (Go back and look at
Figures 13-8, 13-10, and 13-13 for a refresher.) So how does that parent scope link get
created, and can it point to anything other than the global scope?
It turns out that the parent scope points to whatever scope is active at the time that a
function is created. So far, when our functions have been created, the active scope has
been the global scope. That is why the parent scope on our functions has always been
the global scope. If, instead, the function had been created while another function was
active, its parent scope would have been the local scope that was active at the time it was
created! When such a function is called, it still creates a brand-new local scope for its
parameters and all variables declared with the var keyword. However, when referring
to any variable not defined in its local scope, it will look to its parent scope, which will
be the local scope that was active when the function was created. When a computer
programming language stores the scope of an active function as the parent scope for
functions created within that scope, this is known as having lexical closure.
201
Chapter 14 Manipulating Functions and Scopes
Figure 14-7 shows this parent scope manipulation in action. This example was kept
very short so you could more easily see all of the pieces moving. From a high level, the
create_function function takes one parameter and creates a function that always
returns that value. Note the line that says var my_func_a = create_function(12);.
This causes create_function to build a new function that will always return the value 12
and stores this new function in my_func_a.
How does create_function do this? Well, let’s walk through the code.
The first thing that the create_function function does is to create a function. The
function operator can be used anywhere to create a new function. It then stores this
function into new_function, which is a local variable for create_function. It then
returns this newly created function.
What is so special about this newly created function? Since it was defined within
create_function, its parent scope is the local scope that was created at the time that
create_function was invoked. Therefore, each time that create_function is run, it
will create a new version of the new_function function with a different parent scope
(i.e., the one that was created when the create_function function was called). Now,
when create_function returns, its local scope is no longer active, but it is not destroyed
because the function that it returns still refers to it. It will just lie dormant until the
created function is called, and then it will become the parent scope of the created
function’s new local scope.
Therefore, when you call create_function(12), that creates a new local scope with
the variable x, and x is given the value 12 from the parameter list. When the function
that will be stored in new_function is created, the current local scope (with x as a local
variable) is linked to the function so that it will be the parent scope of each new local
scope created from calling the function. This function is then returned and stored in my_
func_a. When my_func_a is called later on, it creates a new local scope for the function
call. However, the parent scope is set to the scope that was active when the function was
created—the scope that has x set to 12. Therefore, when it runs the code return x;, it
first looks in its newly created local scope for x and doesn’t find it. It then goes to the
parent scope and finds x defined there. If it did not find x in the parent scope, it would
move up the chain to the global scope.
Note that my_func_b is created in the same way. However, as we’ve mentioned,
every time a function is called, a new local scope is created. Therefore, when create_
function(20) is called, there is a new local scope created, and this scope has x set to 20.
202
Chapter 14 Manipulating Functions and Scopes
This scope gets attached as the parent scope for the function that is created and stored in
my_func_b. When my_func_a gets called, the parent scope is the one that has x set to 12,
but when my_func_b gets called, the parent scope is the one that has x set to 20.
We now have two different functions that come out of the same code. These
functions both work differently because they have different parent scopes when they are
invoked.
Now, let’s return to the problem of the counter functions. We wanted a function that
would create a new counter function for us. So, what we really want is a counter function
that can be attached to different parent scopes that each has their own current count.
Figure 14-8 shows how this works in code. This code is very similar to the code that
just spits out the value from the parent scope. The only difference is that we manipulate
the value of current_val in the parent scope first (we add one to it) before returning it.
This modification is kept because every time you call mycounter_a, it pulls that same
scope in to be the parent scope. Since current_val is not declared with a var keyword
within counter_function, it will always refer to current_val in its parent scope whether
it is reading or writing the value.
203
Chapter 14 Manipulating Functions and Scopes
Since mycounter_a and mycounter_b were created from different calls to create_
counter, they each maintain different parent scopes and therefore independent values
for current_val. Note, however, that mycounter_c continues on just as if mycounter_a
were called again. Why is that? It is because mycounter_c is not a new function. It is the
same function as mycounter_a since it was simply assigned.
mycounter_a and mycounter_b were both created by a call to create_counter, but
mycounter_c simply gets the same function that was in mycounter_a. Remember that
functions are stored in variables just like any other value and can be assigned back and
forth to different variables, and these assignments do not change the underlying values.
Therefore, mycounter_a and mycounter_c both refer to the exact same function (using
the exact same parent scope).
14.4 Currying Functions
In Section 14.1, we learned how to take multiple, specific functions and combine them
into a single higher-order function that takes a function as a parameter. In this section,
we will look at the reverse process—taking a generalized, or higher-order, function
and creating new, more specific versions of it by specifying one or more parameters
beforehand.
Go back and look at Figures 14-1, 14-2, and 14-3. You will notice that the
functionality of both Figures 14-1 and 14-2 are both present in Figure 14-3. You might
rightly conclude that the function sum_range_with_transformation that is defined in
Figure 14-3 is, therefore, more powerful than the individual sum_cubes_of_range and
sum_squares_of_range functions defined in the other programs. However, sometimes
calling functions that take another function as a parameter can be confusing. If, for
instance, a programmer usually has to sum the squares of a range, but only rarely has
to sum another transformation, it might be useful to have sum_squares_of_range as its
own function.
Now, we still want to make use of our sum_range_with_transformation function.
The reason for this is that if you have code that performs a task, you don’t want to have
two copies of it lying around. If you find a bug in one copy of the function, you would
have to remember to fix it in the other one. If you find a better way of implementing the
function, you also have to remember (and take the time) to rewrite the other function
to match.
204
Chapter 14 Manipulating Functions and Scopes
14.5 Anonymous Functions
Functions are just values. As we learned way back in Chapter 8, you often don’t even
need to create variables to hold each intermediate value. Similarly, we don’t always need
to store functions in variables either.
Just as typing the number 5 produces the value 5, using the function keyword
defines a new function. Let’s look back at the code we wrote in Figure 14-10. Let’s say we
wanted to create a new summing function, but this time we want to raise the members
205
Chapter 14 Manipulating Functions and Scopes
of the range to the fourth power before summing them. Now, we could create a separate
function to raise a number to the fourth power and then just use the technique in
Figure 14-10. However, an easier way would be to skip naming the function altogether
and define it when we call create_summing_function. The result would look something
like Figure 14-11, which would be appended to the program you wrote in Figure 14-10.
As you can see, where in Figure 14-10 we used a named function for the
transformation, here we are passing in the function directly. The function we are passing
in has no name. It is defined and, rather than being stored in a variable, is simply passed
as a parameter to a function. Functions that are defined within the code and not given a
name are known as anonymous functions.
14.5.1 Review
In this chapter, we learned several advanced ways of creating and using functions. We
have learned the following:
206
Chapter 14 Manipulating Functions and Scopes
• When two functions look almost the same except that they each
perform a slightly different process, they can often be combined into
one function that takes a function as a parameter.
• The link to the scope will be used as the parent scope when a local
scope is created for each function invocation.
2. Modify the counter program further so that you can also specify a
“skip” value (i.e., progress the counter by more than 1 per call).
3. Modify the program in Figure 14-11 to perform another
transformation. If you need an idea, try just doubling the values.
207
CHAPTER 15
Intermediate Objects
So far, we have created objects that just contain data. Objects that just contain data are
sometimes known as records—they store data, but they don’t do anything. In Chapter 11,
we wrote functions that manipulated these records. If you want to perform an action
(such as withdrawing funds from an account), you would call the appropriate function,
and it would do what you want. This is a fine programming style and works well for many
situations. However, as programs get larger and more complex, it is beneficial to make the
functions that operate on the objects more tightly connected to the objects themselves.
In Chapter 11, we grouped together several related variables into a single object. This
made several improvements to our code:
1. It used fewer variables since the values were all properties of one
variable.
209
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_15
Chapter 15 Intermediate Objects
Let’s say that we had an object that represented a car. It will have two values—the
number of miles traveled and the amount of gas left. Now, let’s say we have a function
that drives us ten miles. What needs to happen? Well, that function would increase the
number of miles driven and decrease the amount of gas left.
Figure 15-1 has the code for such an object. As you can see, the drive_car function
relates several different values—the number of miles traveled, the amount of gas left
in the tank, and the car’s gas mileage. Since the drive_car function is so tightly related
to the car abstraction, it makes sense to just attach the function directly to the my_car
object, like in Figure 15-2.
As you can see, we assign the function the same way that we assign the rest of the values.
We could have also done it the long way by typing my_car.drive = function() { ...},
but this way is simpler.
So how do you call the function now that it is in the object? Well, all function calls
that we have made in this book have been made by simply typing the name of the
variable which holds the function (usually a global variable) and calling it by adding
parentheses and listing the parameters to pass to the function. It is done the same way
here. The only difference is that since the function is stored in the object rather than in a
global variable, we have to access the function value as a property on the object.
So we would write the following:
my_car.drive(my_car, 50);
What advantages does this give us? Not many yet. However, one important thing that
this accomplishes is to have fewer global variables since, so far, we have usually stored
functions in global variables. Now the function is only stored within the car object. For
our simple programs, this might not seem important, but, in large projects, the number
of functions can grow to thousands. In those cases, keeping the set of global variables to
a minimum is essential for sanity.
210
Chapter 15 Intermediate Objects
Along the same lines, note that when it was a global variable, we named it drive_car.
We gave it the longer name to prevent name clashes—where two functions accidentally
get the same name. When you put functions in global variables, you usually have to
give them very long names to prevent someone else from accidentally calling another
function the same name. This is not the case when the function is stored on the object
211
Chapter 15 Intermediate Objects
itself. Additionally, if the function is only attached to the object, we already know that it
is operating on a car, because that is where we assigned it. Therefore, we shortened the
name of the function to just drive, which makes the code clearer and easier to write.
One issue, though, is that the drive function looks a bit redundant. The code is
calling the drive function on the object but is also having to pass in the object as a
parameter. It turns out that almost every function you define on an object requires the
data of the object to be present. Therefore, if you look up a function on an object using
a property (i.e., car.drive), JavaScript has a way to implicitly send the object (i.e., car)
to the function without having to make it a parameter. JavaScript has a special variable,
always named this, which holds the object that was used to look up the function (if
there was one). It is called this because it refers to “this current object that we are using.”
Therefore, we can remove the parameter the_car from the function because it will
be automatically passed in through the variable this. Taking advantage of the this
variable, we can write our code as shown in Figure 15-3.
So, while most parameters to functions are explicitly passed to the function because
we named them when we defined the function, the this parameter is implicitly
passed to the function—it is not in the parameter list. Instead, JavaScript handles it
automatically behind the scenes.
In object-oriented programming, functions which are defined on objects and make
use of the this variable are often referred to as methods or also as messages. Unlike
other languages, in JavaScript, the distinction between a function and a method is only
in the way that you use it—if your function makes use of the this variable, it is a method.
You can also think of methods in terms of human language. The object is the subject,
the method is the verb or command, and the function parameters are the direct object,
adverbs, or other modifiers.
212
Chapter 15 Intermediate Objects
213
Chapter 15 Intermediate Objects
and modify it. Because all of the functions surrounding my_car are defined near each
other, when a change needs to be made, it is easier to find related functions which also
need to be modified in tandem.
When you program larger programs, it is sometimes difficult to keep track of what is
happening to the data throughout the program. If you remove a field or change how it is
used, how will you know if you modified the rest of the code to use it correctly? By baking
all of the code related to an object into the object itself, it is easier to find the places
where changes need to be made when the code for an object is modified.
Programming is not just about making your programs work. You also must make
them understandable and modifiable by both yourself and others. Thinking through
what objects you need, what functions they need to work, and what pieces of data they
need will help you make better objects which will help you both now and in the future. It
will make your code more readable, understandable, and maintainable.
Object-oriented programming has more benefits, though, than just the fact that it
makes your code easier to read and understand. Object-oriented programming allows
you to use objects, not based on the data they contain but based on the functions they
can perform.
We already have code that allows us to drive a car. Let’s say that we invented a new
kind of magic car that is not limited by gasoline at all. It can drive any number of miles
that you want. Such a car can be implemented using code shown in Figure 15-4.
This object isn’t nearly as complicated as our previous object, but that’s not what I
want to emphasize. Do you notice that this object also has a drive method? The function
operates differently for this new kind of car, but it has the same name and takes the same
parameters as the drive function on our other object.
This allows us to write functions and methods that take an object as a parameter
without having to care exactly what the object is. In other words, if I have a function
that needs to use the drive method, that function doesn’t have to care which
214
Chapter 15 Intermediate Objects
version of the drive method it is using. Whether it is a car or a magic car, as long as
my function uses the drive method, then I can use the either type of object for the
function.
15.3 Constructing Objects
Having a single object with a function attached does not give us a lot of progress. Most
programs have lots and lots of similar objects. Building objects with a set pattern is
known as constructing objects, and functions that construct objects are known as
constructors. JavaScript has several different ways of constructing objects. However,
since this is an introductory book, we will only look at one—constructor functions.
A constructor function is a function that is called with JavaScript’s new keyword.
Constructor functions, by convention, are named starting with a capital letter, so they
can be readily identified as a constructor function. Let’s say that I wanted to write a
constructor for my car that takes the starting amount of gas in the car.
Such a function might look like Figure 15-5. Notice that we created the car by saying
new Car(50). What this did was create a new blank object and set it as the this object
for the Car() function. We then called the Car function with 50 as the parameter. The new
keyword, rather than relying on the function returning a value using the return keyword,
instead returns the newly built object that was used in the this variable.
In this program, the Car function is a constructor. It works together with the new
keyword to build a new object for use. The function doesn’t have to start with a capital
letter, but most JavaScript programmers follow this convention to make sure that it is
clear which functions are supposed to be used as constructors.
In some programming languages, Car would be considered a type or a class. A class
gives a programmer an expectation of what the object can do—what properties it will
have, what functions it will have, and how they work together. This is somewhat similar
to a constructor in JavaScript because the constructor sets up the initial properties and
functions on an object.
215
Chapter 15 Intermediate Objects
This means that most objects that are made by a constructor will have similar
properties and functions.
15.3.1 Review
In this chapter, we covered the basics of how to attach functions to objects. We have
learned the following:
216
Chapter 15 Intermediate Objects
217
Chapter 15 Intermediate Objects
218
PART V
Programming
Applications
In this part of the book, we will look at some basics of how an application works. We will
look at modifying a page using JavaScript, accessing an external service, and even writing
a simple service.
CHAPTER 16
Modernizing JavaScript
Before we get started in some of the details about how applications in the real world
are written, I wanted to take a moment and introduce you to some modern features of
JavaScript which are commonly used in modern applications. Note that the goal of this
book is not to provide a comprehensive introduction to JavaScript itself but rather to
use JavaScript as a jumping point for learning programming in general. Nonetheless, I
wanted to take some time and introduce a few modernizations of JavaScript that have
been introduced over the years which you are likely to run into if you read JavaScript
code. None of these are radical departures, but they do make JavaScript a little easier to
read and write.
JavaScript was originally written with a primary goal of being simple, easy to
implement, and easy to learn. The basic ideas behind JavaScript are sufficiently simple
that the author of JavaScript originally wrote JavaScript in only 10 days. However, as it
has become more and more widespread as a programming language, additional features
have been added on.
In this chapter we will look at some of the more commonly used additions to
JavaScript that have been added over the years. Additionally, we will also hit on some
older features that are important but haven’t yet been discussed in the book.
221
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_16
Chapter 16 Modernizing JavaScript
First of all, the var keyword can occur anywhere in the function, and it still backward-
applies to the usage of the variable previously in the function. If you declare a variable
with var more than once, these all get bundled into a single variable declaration. Finally,
being function-scoped is somewhat of a surprising feature, as most programming
languages delineate scopes at the block level.
Because of these drawbacks, more recent iterations of JavaScript introduced the let
keyword for declaring variables. Using let is very similar to var, with some important
distinctions:
• Every time you use the let keyword, it declares an entirely new
variable.
• If you try to use let twice in the same scope for the same variable, it
will generate an error.
The code in Figure 16-1 illustrates the differences. Following along will help you see
the differences in how the two ways of declaring variables behave.
Another keyword for declaring variables is const, which stands for “constant.” This
works very similarly to let, except that, once assigned a value, the variable cannot have
another value assigned to it. This is helpful in two ways. First, it enables optimizations
within JavaScript that can make your code faster if you have code that needs to execute
quickly. Second, and even more importantly, it helps you to remember which variables
are actually varying and which ones are supposed to be left alone. The const keyword
will remind you that this variable is only supposed to be assigned once, and, if you forget,
the subsequent assignments to that value will yield errors.
The last lines of Figure 16-1 will give an error because the constant value is
reassigned.
222
Chapter 16 Modernizing JavaScript
In most modern JavaScript applications, let and const are preferred to var. We have
used var primarily because it is more forgiving for beginners and reflects a lot of existing
documentation on JavaScript. However, if you go further, you will probably see let and
const quite a bit.
16.2 Destructuring Assignments
One thing that saves a lot of typing is what is known as a destructuring assignment.
Let’s say you have an array myary that has the value [23, 43, 5]. Now, let’s say that you
want to separate these values into the variables x, y, and z. Usually, you would do that
like the following:
223
Chapter 16 Modernizing JavaScript
let x = myary[0];
let y = myary[1];
let z = myary[2];
What this says is that we should expect that myary is structured in such a way that
it looks like the left-hand side and that we should assign the variables accordingly. Any
additional members of the array are ignored, and if there aren’t enough members of the
array, the variable will be filled with undefined.
This also works with objects as well. Let’s say that we have an object that looks
like this:
var myobj = {
field1: "val1",
field2: "val2",
field3: "val3"
};
Let’s say that we wanted to extract field1 and field2 into their own variable. This
can be done as follows:
Destructuring is very helpful when you want to extract several pieces of an object
or an array without having complicated code. You simply mirror the left-hand side so
that the variable you want to assign is in the same location that you are expecting on the
right-hand side. You can embed arrays within objects within arrays and so forth.
As mentioned, this book is not intended as a complete JavaScript book, but I did
want to let you know about some pieces of syntax that are both helpful and you are likely
to see out in the wild.
224
Chapter 16 Modernizing JavaScript
var theperson = {
name: "Jim",
age: 20,
hair: "brown"
};
Now, we already know how to access individual properties of this object using
theperson.name or theperson.age. However, we can also ask the object for a property
that is named by a string. If we want the name property, I can ask for it by doing
theperson["name"]. By putting this on the left-hand side of an assignment statement, I
can set a field in this way as well, whether or not it existed beforehand.
Because this is a string, I can use a variable as well.
This means that a user can even say what field they would like to access.
This allows for a huge amount of flexibility in both the creation and usage of
object fields. In fact, property names can actually be arbitrary strings and don’t even
have to be accessible in the “normal” syntax. For instance, I could set a field like
theperson["some,;/field–+"]. If we tried to access that field using the normal method,
we would get a syntax error. But it is a perfectly valid operation as a string.
There are many cases where it is useful to have an object serve as a random grab-
bag of key-value pairs. Using objects in this way allows you to do this. In computer
programming, objects used in this way are referred to variously as dictionaries,
hashtables, maps, or associative arrays.
225
Chapter 16 Modernizing JavaScript
16.4 Function Syntax
So far we have declared functions by typing something like the following:
This syntax was chosen to emphasize the distinction between creating a function
and assigning a name to that function. I think doing it this way helps make it easier to
understand how creating and passing functions as parameters works (like we did in
Chapter 14). However, there is a combined syntax that does both at once that is much
more commonly used. The same snippet above, using this other syntax, looks like this:
However, modern JavaScript adds yet another way to create functions, which is
known variously as lambda functions or arrow functions.1 Creating the same function
using lambda/arrow functions looks like this:
The meaning is (almost) the same, but it gets rid of the annoyingly long function
keyword.
There are indeed some slight differences to regular functions, but usually they are
unimportant. The main differences are as follows:
• Regular functions get another special variable we haven’t talked
about, known as arguments. This is essentially an array of all
arguments passed to the function, which allows functions to be
called with more arguments than are shown in the parameter list.
Arrow functions do not have this special variable.
1
The term “lambda function” comes from an early conception of computer programming known
as “lambda calculus,” which focused on creating functions dynamically using an operator known
as the “lambda” operator. The term “arrow function” comes from the fact that the syntax uses the
characters => which looks like an arrow.
226
Chapter 16 Modernizing JavaScript
• Arrow functions do not overwrite the this variable (see Chapter 15).
If you want to inherit the current this variable being used, arrow
functions will help out. If you want to make an object method, you
should use the traditional syntax.
• Regular functions can be called with the new keyword to build objects
(again, see Chapter 15). Because arrow functions do not work with
their own this variable, you cannot use arrow functions in this way.
So aside from a few edge cases, arrow functions are basically identical to the syntax
we’ve used so far. However, while it might seem trivial, the fact that arrow functions don’t
clobber the this variable comes in handy quite a bit. If you are writing a method inside
an object and need a dynamically created function, you can choose a regular function or
an arrow function based on whether or not you want this to be overwritten.
16.4.1 Review
In this chapter, we learned about additional syntax available in JavaScript. We learned
the following:
• Variables can be declared with the let and const keywords for block
scoping and slightly cleaner behavior.
• The arrow syntax for functions does not overwrite the this special
variable.
227
Chapter 16 Modernizing JavaScript
228
CHAPTER 17
Working with Remote
Services (APIs)
One of the most fundamental aspects of modern computer programming is writing
a program that interacts with servers. JavaScript is primarily a front-end language,
meaning that it usually deals with the interactions with the user. There is usually some
database or other remote service somewhere where your data is stored, retrieved, or
manipulated from. So how do you access these services?
Many if not most modern services are accessed via HTTP/HTTPS requests on the
Web (go back to Chapter 3 to refresh yourself on HTTP). Essentially the servers are
constructed so that the URL tells the server what data you want or want to modify, and
the server responds appropriately. Therefore, by knowing what these URLs look like
and what the server is expecting, you can construct URLs and HTTP requests to fetch,
modify, and manipulate data on the server.
The specifics of the structure of the URLs and how they should be accessed via HTTP
is known as an application programming interface, or API. APIs actually refer to any
documented interface for programming another system. For instance, all of the standard
JavaScript objects and functions (such as alert, prompt, document, etc.) are part of the
JavaScript API.
However, for this chapter, when we refer to an API, we are referring to a remote
service’s documented interface over HTTP.
Many APIs cost money to use, but there is one API that is free now and almost certain
to remain free in the future because you already pay for it with your tax dollars: NASA’s
Data API. This API provides a gateway to all sorts of data gathered and curated by NASA
itself. The NASA API includes the following:
229
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_17
Chapter 17 Working with Remote Services (APIs)
You can find out general information about NASA’s API at api.nasa.gov.
hgohi60L0JLMZProclQIY2ku1lXebMHfMlxXQ94E
You will need to copy that down so that you have it for the future. For all of the
examples in this chapter, we will refer to this simply as APIKEY. So, wherever you see
APIKEY, replace it with the value you received from NASA.
You can simply use your browser to try out your API Key. Go to the following URL
and you will see information about NASA’s astronomy picture of the day:
https://api.nasa.gov/planetary/apod?api_key=APIKEY
230
Chapter 17 Working with Remote Services (APIs)
var obj = {
mykey: "myval",
myotherkey: [1, 2, 3]
};
var str = JSON.stringify(obj);
console.log(str);
var newobj = JSON.parse(str);
console.log(newobj);
1
In fact, HTML is essentially a set of tags within XML. There are some historical technical
distinctions, and HTML is generally processed in a more forgiving way than XML, but, on the
whole, you can generally think of HTML as being a set of tags in XML.
231
Chapter 17 Working with Remote Services (APIs)
When this runs, it will first log to the console a string which contains the JSON
representation of the object which should roughly match the JavaScript. The second
log will be the object that is created from processing the JSON code. As a note of
terminology, turning a programming language data structure into a transmittable
or storable structure (like a string) is known as serialization, while taking the
transmittable/storable structure and generating the programming language data
structure again is known as deserialization.
232
Chapter 17 Working with Remote Services (APIs)
In our code, we called then with a function that took one parameter, response, which
is the response that we get back from communicating with NASA’s web server. In order
to get the JSON value of the response, we have to call the json function of the response,
which will make sure we have all of the data and then, assuming it is in JSON format, will
convert it to a JavaScript object. However, this too comes wrapped in a Promise, which
requires that we call then and send it a function it can call when the data is all ready.
Finally, when our data comes in the parameter jsonval, we can access all of the
fields we received. These are the same fields you observed when you accessed the URL
yourself. We used the title field to display to the user. Feel free to try with other fields
as well.
https://api.nasa.gov/planetary/apod?api_key=APIKEY
Notice there is a single key=value pair attached to the end of request following the
question mark. The API also allows for other query parameters to be added as well.
While the API has a number of keys that it supports for its query string (you can see more
at api.nasa.gov), we will focus on one: date. This will give you the Astronomy Picture
233
Chapter 17 Working with Remote Services (APIs)
of the Day for that particular date. The API states that this must be given in a specific
format, namely, YYYY-MM-DD. So, for August 3, 2009, the date would be formatted as
2009-08-03. The following URL incorporates this into the query string:
https://api.nasa.gov/planetary/apod?api_key=APIKEY&date=2009-08-03
Note that it may be tempting to manually construct these URLs from a string; there
is a standard class called URLSearchParams that will handle this for you. To generate the
preceding URL, you can do the following:
var query = {
api_key: "APIKEY",
date: "2009-08-03"
};
var query_string = new URLSearchParams(query).toString();
var full_url = "https://api.nasa.gov/planetary/apod?" + query_string;
234
Chapter 17 Working with Remote Services (APIs)
235
Chapter 17 Working with Remote Services (APIs)
As you can see, this code has the same basic structure as Figure 17-1 but expands it
in the following ways:
You will find that a lot of programming on the Web consists of precisely these kinds
of interactions.
236
Chapter 17 Working with Remote Services (APIs)
• GET is for getting data that already exists on the server, specifically
identified by a URL.
• POST is for creating data that doesn’t already exist on the server.
The URL used here is generally the same URL every time you create
something new.
Since PUT and POST are for sending data, they also support what is known as an entity
body or payload which can be sent along with the request. There are a variety of ways
in which this data can be encoded, but the two most common are either (a) the same
format as the query string or (b) using JSON.
Along with your data, oftentimes when accessing remote APIs you also have to send
specific HTTP headers (we learned a little about HTTP headers back in Chapter 3). One
particular header is the Content-Type header, which most services require that you send
with PUT/POST payloads describing how they are formatted (for reference, the Content-
Type of a query string formatting payload is application/x-www-form-urlencoded and
the Content-Type of a JSON payload is application/json).
The following is a simple example of using an HTTP POST method to a payload, just
so you can see all of the pieces in place:
var myobject = {
a: 1,
b: "someval"
};
237
Chapter 17 Working with Remote Services (APIs)
fetch("https://www.example.com/some_endpoint", {
method: "post",
headers: {
"Content-Type": "application/json",
"Other-Header": "My other header value"
},
body: JSON.stringify(myobject)
}).then((response) => {
// Do something with the response.
});
For detailed information about how this all fits together, it depends entirely
on the API you are accessing. This section just tells you what sort of things the API
documentation will be referring to.
A NOTE ON CORS
I wanted to take a moment to mention CORS to you. This is somewhat outside the scope of
what this book is aiming for, but I thought I’d mention it before it causes you problems. CORS,
which stands for “cross-origin resource sharing,” is a browser security feature that allows a
web server to tell browsers what website they are expecting traffic from. The idea is to prevent
a browser window looking at one page to trigger actions on another website. Therefore, before
making a request, the browser will “preflight” the request to the server to check and see if the
request is coming from a valid source.
I mention this because, if you try to attempt to access an API but you keep on getting nothing
but errors back, it is possible you are running into CORS errors. This is especially true if
you are building your own API (which we will cover a little bit of in Chapter 18). You have
to explicitly whitelist any host that you are receiving requests from that is not the same as
the server that is hosting the JavaScript. Usually, if there is a CORS problem, the JavaScript
console will mention either “CORS,” “cross-origin,” or “preflight” problems.
There are a lot of nuances involved here, but I mostly wanted to make you aware of the issue
before spending days trying to figure out why something isn’t working.
238
Chapter 17 Working with Remote Services (APIs)
17.6.1 Review
In this chapter, we practiced accessing a remote JSON-based API with JavaScript. We
have learned the following:
• Many APIs have their accessed managed through an API key which
contains the user’s access credentials to the service.
• Additional data can be sent via HTTP using the query string, which is
usually formatted with key=value pairs.
• HTTP has multiple methods which can be used for data access. The
default method is GET, but there is also PUT, POST, and DELETE.
• The PUT and POST methods can take an HTTP entity body to allow for
more data than may be supported by the URL alone.
239
Chapter 17 Working with Remote Services (APIs)
• Using the fetch function, the programmer can also send additional
HTTP headers as well.
2. Modify the previous program so the user can enter how many
pictures they want to view. Note that, for this one, you will need to
dynamically add and remove <img /> tags based on the number
of pictures the user requests.
3. Look through NASA’s list of APIs. Look for one that you find
interesting, and practice accessing it with your browser. Now write
an interface with HTML and JavaScript for accessing this API.
240
CHAPTER 18
Writing Server-Side
JavaScript
So far, we have written user interfaces, but we are only accessing other people’s server-
side code. In this chapter, we are going to take a very brief look at the other side of the
equation and give you a quick taste of server-side programming. The goal of this chapter
is not to even get you fully set up for doing server-side programming. That would require
an entire additional book. However, I do think it is important for you to know at least a
little bit about what goes on there.
18.1 Programming Languages
While the user-facing side of web programming (also known as front-end or client-
side programming) is done almost exclusively in HTML and JavaScript, on the server
(also known as back-end programming), JavaScript is actually much more rarely used.
Additionally, programming languages are rarely used by themselves but are instead
used along with application frameworks which automate many of the tasks which are
required to do server-side programming. Note that there are also front-end application
frameworks (such as React, JQuery, and Angular, just to name a few), but it is a lot
easier to write front-end applications without a framework than it is to write back-end
applications.
The following are some popular programming languages that are often used on the
server, with the name of common application frameworks for them in parentheses:
241
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_18
Chapter 18 Writing Server-Side JavaScript
• C# (ASP.NET)
• JavaScript (Express)
The list of languages (and frameworks for them) is nearly endless, each with their
advantages and disadvantages. My recommendation (for your next book purchase)
is to pick one that looks easy to start with. This will probably not be the one you stick
with, but having early, easy wins helps you to get more familiar with how everything
works. Sometimes complicated frameworks are necessary, but it is better to start with
something simple, and that way you will gain the experience to know why it is the
complicated frameworks need their complications.
For myself, if I’m trying to write something quickly, I write it in Ruby using the Rails
framework. When Rails was first introduced, you could write the same applications as
before using only 10% of the code previously required! Today, many of the features of
Rails are adopted by other frameworks, but I still think that Rails makes it easiest to write
server-side applications quickly.
Other than that, I usually write code based on the requirements of the company
I work for. Most companies don’t want to have to maintain a whole host of programs
written in different languages, so they generally try to standardize on a few. This means
that, on the whole, you will generally not be choosing the server-side language you work
with, so you should prepare yourself for the fact that you will probably have to learn
several through your career.
In this chapter, since we’ve taken the time to learn JavaScript already, we will do a
short example using JavaScript and the Express framework.
242
Chapter 18 Writing Server-Side JavaScript
by downloading it from nodejs.org. You will need to be on the command line to run
the commands in this section. You can find a short introduction to the command line in
Appendix B.2.
The following is a simple Node app, which just writes to the output. You can call this
file myapp.js.
console.log("Welcome to Node!");
After you have installed Node, you can run this JavaScript file using Node from your
command line by typing node myapp.js. The language features of Node are identical to
standard JavaScript, but the browser-based features (such as alert, prompt, document,
etc.) are missing, and some extra functionality is included.
243
Chapter 18 Writing Server-Side JavaScript
You can run this code just by running node nodeserver.js on the command line.
This can be accessed with your browser by going to http://localhost:3000/
whatever. We are using http instead of https because HTTPS requires a lot of additional
setup to use. localhost is a standard name that refers to the machine that the browser
is on. The :3000 addition tells the browser to look at port 3000 instead of the standard
port (80). Then the path is everything coming after (starting with the slash). The server
function will respond to any path given to it.
244
Chapter 18 Writing Server-Side JavaScript
databases, querying them, and getting the data back to your application in a usable
form is sometimes quite time-consuming. Therefore, these operations are likewise often
assisted by frameworks.
Frameworks often have other features, too, like job scheduling (i.e., run a report at
midnight and send it somewhere), resource management (make sure nobody is calling
an endpoint too often), interfacing with other services, and prebuilt data manipulation
functions. Because of all of these features, application developers usually opt for using
full frameworks rather than just serving requests directly.
• You need to configure your server so that it runs the language and
framework you have chosen.
• You need to make sure your application starts when the server starts.
• You need to make sure the DNS record for your domain name points
to the correct IP address of your service.
• You need to register for, install, and maintain SSL certificates on your
server to enable HTTPS connections.
As your service gets bigger, you need to look at making your service scale (i.e., run
faster using more machines). For that I suggest my book Cloud Native Applications with
Docker and Kubernetes.
1
If you use AWS, you should use Lightsail, as it is a lot less complicated than their other offerings.
245
Chapter 18 Writing Server-Side JavaScript
18.5.1 Review
This chapter covered a little bit about server-side development. We have learned the
following:
• Node.js comes with an http module that enables you to easily write
HTTP service code.
246
Chapter 18 Writing Server-Side JavaScript
247
CHAPTER 19
Conclusion
Congratulations—you have taken the first steps into the wide world of programming.
This book introduced you to the basics of computers, the Internet, web pages, CSS, and
JavaScript. However, this book certainly didn’t teach you all there is to know about any of
these subjects.
Hopefully now you have a basic feel for what it is like to write and run a program and
the kind of thought-work required to make a program run successfully. Where you go
from here is up to you. If you like websites, then you should dig deeper into the topics
covered here—HTML, CSS, and JavaScript. Learning a JavaScript framework like React or
JQuery might also be a good idea. Other than that, there are all sorts of specialized tools,
languages, and techniques for programming different devices and applications. There
are tools and languages for database systems, phone apps, e-commerce apps, games,
microcontroller systems (tiny devices with small chips), and desktop applications. Each
of these has its own specialized tools and languages.
Your first language, however, is usually the hardest. Once you get used to the
idea of statements, loops, variables, and functions, then, even if different languages
do things differently, you have already trained your mind to think in these terms.
Learning JavaScript may have been challenging, but it should make your next language
much easier.
Keep in mind that software development is very dynamic. A programmer spends
much of his or her life staying on top of new languages, tools, and techniques that are
continually changing.
You’ve got a good start. Now build on it.
249
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4_19
APPENDIX A
Glossary
The following are the definitions of the bolded glossary terms used throughout the book,
plus additional terms you are likely to run into when reading about programming. When
a term has more than one usage, the context for the term is distinguished in parentheses.
251
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4
Appendix A Glossary
arithmetic and logic unit The arithmetic and logic unit is the
part of the Central Processing Unit that performs math and logic
functions. See also Central Processing Unit.
252
Appendix A Glossary
back end The back end of a system is the code that is running
on the remote server. This is usually responsible for the ultimate
storage and processing of data. See also front end.
base URL The base URL is the starting point for relative URLs. The
base URL is usually set to the URL of the current document being
254
Appendix A Glossary
viewed, but in HTML this can be adjusted using the <base> tag.
See also URL, fully qualified URL, relative URL.
255
Appendix A Glossary
byte A byte is a sequence of eight bits and therefore has the ability
to hold a number between 0 and 255. While individual bytes are
rarely used in computer programs anymore, most quantities
on computers are given in terms of bytes, such as the size of
computer memory chips and hard drives. See also bit, binary.
256
Appendix A Glossary
257
Appendix A Glossary
258
Appendix A Glossary
control unit The control unit is the part of the Central Processing
Unit that interprets instructions and directs the other parts of the
CPU. See also Central Processing Unit.
259
Appendix A Glossary
data link layer The data link layer is the second layer of a
networking system according to the OSI model. The data link layer
deals with how the data on the physical layer will be divided and
interpreted. It usually has a methodology for naming each local
device (often called a MAC address). See also OSI model, MAC
address.
260
Appendix A Glossary
261
Appendix A Glossary
262
Appendix A Glossary
synchronized with each other, (b) make sure that all business
and domain rules are appropriately followed concerning the
data, and (c) make sure that the interface (the functions or
methods) does not have to change even when the underlying
data fields may change. For instance, a bank account might be
encapsulated by giving the programmer no direct access to the
account balance but giving methods to check the balance, deposit
money, and withdraw money. In this way, it can ensure that if the
programmer calls the functions to withdraw money, for example,
all overdraft rules are appropriately applied rather than relying
on the programmer to always remember to apply them. This also
allows the implementation of these functions to change without
drastically impacting other parts of the program.
end tag In HTML, an end tag marks the end of a block of content
that is used for a specific purpose. An end tag looks just like a
start tag but begins with a slash. So, if the start tag was <p>, then
the end tag will be </p>. See also tag, start tag, markup language,
HyperText Markup Language.
entity body For HTTP PUT and POST methods, the entity body is
the main data stream which is sent to the service which passed
separately from the URL. The format of the entity body should be
noted in the Content-Type header of the request.
263
Appendix A Glossary
264
Appendix A Glossary
265
Appendix A Glossary
for loop A for loop is a type of loop that includes some amount
of loop initialization and control management. In JavaScript, it
takes the form for(initialization ; loop condition ; loop
control ) { loop body }.
front end The front end of a system is the part that the user
interacts with directly. On the Web, the front end is usually written
in a combination of HTML, CSS, and JavaScript.
fully qualified URL A fully qualified URL (also called an absolute
URL) is a URL that contains all of the information needed to
access a remote document or service. As opposed to absolute
266
Appendix A Glossary
267
Appendix A Glossary
268
Appendix A Glossary
269
Appendix A Glossary
270
Appendix A Glossary
271
Appendix A Glossary
272
Appendix A Glossary
hold the value given in the right-hand side. Therefore, the left-
hand side is interpreted differently than the right-hand side. On
the right-hand side, myarray[0] refers to the value that is held in
the first element of myarray. On the left-hand side, myarray[0]
refers to the storage location that is the first element of myarray.
Storage locations specified by the left-hand side of assignment
statements are often called L-values. See also assignment
statement, right-hand side.
lexical closure Lexical closure is the idea that functions that are
defined inside of other functions have full access to the variables
defined in their containing scope. Even if the containing function
returns, if a function was defined inside that scope and returned
from that function, the scope remains “alive” whenever the
returned function is called.
273
Appendix A Glossary
275
Appendix A Glossary
276
Appendix A Glossary
277
Appendix A Glossary
278
Appendix A Glossary
octal Octal is a numbering system that only uses the digits 0–7. It
is commonly used in computers since each octal digit represents
exactly three bits. See also binary, decimal.
OSI model The OSI model is a way of thinking about the different
needs of a communication system broken out into independent
layers. The OSI model is what, for instance, allows wired and
wireless computers to interoperate on the same network despite
having very different ways of physically connecting to the network.
The OSI model divides the needs of a network communication
system into seven layers which can each act independently of
the others. See also physical layer, data link layer, network layer,
transport layer, session layer, presentation layer, application layer.
279
Appendix A Glossary
280
Appendix A Glossary
POP POP (the Post Office Protocol) is one of the application layer
protocols used to retrieve email from an email server. See also
application layer, SMTP, IMAP.
281
Appendix A Glossary
282
Appendix A Glossary
283
Appendix A Glossary
relative URL A relative URL is a partial URL that uses the current
base URL as the starting point for the URL. In URLs, directories
are separated by slashes (/), and the relative URL starts in the
same directory as the base URL. For instance, if the base URL is
www.npshbook.com/example/example.html, then a relative URL of
test.html would refer to www.npshbook.com/example/test.html.
A directory of .. refers to the parent directory so a relative URL of
../test.html would refer to www.npshbook.com/test.html. If a
relative URL starts with a slash, it becomes an absolute path. See
also URL, fully qualified URL, base URL, absolute path, directory.
285
Appendix A Glossary
stack The stack is the part of computer memory that holds the
call-specific information of all active functions. The stack usually
holds things like parameters, local variables, and the point in the
code to return to when the function is finished. Think of it as a
scratch pad for active functions. It is called a “stack” because every
time a function is called, the information for the new call (newly
created local variables, the parameter list, and the location where
we left off the last function) is placed “on top of the stack.” Then,
when the function is finished, that information is pulled off of the
top of the stack to let the previous function continue running. See
also stack frame.
stack frame The stack holds information about all active function
calls currently in progress. A stack frame is the information for a
specific function call. The stack frame usually holds information
286
Appendix A Glossary
287
Appendix A Glossary
288
Appendix A Glossary
289
Appendix A Glossary
291
Appendix A Glossary
while loop A while loop is a type of loop that takes the form
while( loop condition ) { loop body }. The loop condition
is evaluated before each iteration of the loop body. If the loop
condition is true, it executes the loop body. If the loop condition
is false, the loop body is skipped and the program goes to the next
statement. The loop is evaluated over and over again until the
loop condition is false. See also loop, loop condition, loop body.
292
APPENDIX B
Operating System
and Browser Specifics
JavaScript is a great programming language to learn because it can be used on any
modern computer, using any browser. However, there are some minor differences
between computers and operating systems so that things might look and work a little bit
differently depending on which computer you use. When the main chapters reference
a technique or a feature that is more system-specific, this appendix gives you additional
context and information so that you are more likely to be able to find it on your
computer.
However, there are hundreds of different systems and system configurations, and I
can’t possibly list them all in this book. All of the different versions of Windows (7, 8, 10,
11, etc.), Mac (Catalina, Big Sur, Monterey, Ventura, etc.), and Linux (Red Hat, Ubuntu,
CentOS, etc.) have slightly different ways of doing things. Therefore, this appendix will
cover just a few representative systems, which should give you enough background
information to find the right setting on your own system. If you still have questions
on how to do this on your own system, hopefully this appendix will give you the right
context and ideas for what you need to ask someone about, either in person or in an
online forum.
You will find that developers often wind up with their computers set up much
differently than the average user. The reason for the difference is simple—ordinary users
want all of the messy details hidden from them. Programmers, on the other hand, use
the messy details to accomplish tasks. The average user wants to know less about what
is going on behind the scenes, but programmers need to know more. Therefore, the
defaults, made for the average user, focus on hiding technical information. Programmers
tend to adjust all of their settings to show all of the gritty details.
293
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4
Appendix B Operating System and Browser Specifics
294
Appendix B Operating System and Browser Specifics
In most browsers, even if the whole URL is not displayed, if you copy and paste
the URL to a different document, it will paste the full URL. If you want to see the full
URL displayed while you browse, several browsers have options for that. In Safari, for
instance, if you go to the “Safari” menu, then click “Preferences” it will open up a dialog
box. Under the “Advanced” settings, there is a checkbox that says “show full website
address.” If you click that, it will display much more of the URL. It still hides the protocol,
but it will show you the rest. In Chrome and Brave, in “Preferences,” under “Appearance,”
there is a “Always Show Full URLs” option that you can select.
295
Appendix B Operating System and Browser Specifics
After using getting a command line, you might also take a look at Appendix C.
296
Appendix B Operating System and Browser Specifics
297
Appendix B Operating System and Browser Specifics
and can really make everything easier. If you don’t already have a text editor you like, I
would suggest you try Visual Studio Code first.1
However, you can also work with the tools you already have installed on your
operating system. I want everyone to know that programming doesn’t require a bunch of
extra tools but that, on modern computer systems, your operating system already ships
with everything you need to get started. Therefore, each of the following section tells you
how to get to your system-installed text editor. But I would still recommend that you use
Visual Studio Code instead.
1
Despite the similarity in name (and despite also being published by Microsoft), this program
has no real connection to Microsoft’s Visual Studio development environment. Visual Studio
is geared toward writing Windows-oriented applications, while Visual Studio Code is a
programmer’s text editor that can be used for just about any project on any operating system. I
personally use Visual Studio Code whether I am on a Mac, Windows, or Linux, for just about every
programming project. It’s free and it is easy to use.
298
Appendix B Operating System and Browser Specifics
7. You also might want to find the “Hidden files and folders” option
and select “Show hidden files, folders, and drives.” This isn’t
needed for this book, but I didn’t ever know a programmer who
didn’t use that setting.
299
Appendix B Operating System and Browser Specifics
To open up TextEdit, you can just click on the Spotlight Search icon and type in
“textedit.” Clicking on the TextEdit icon will open up the application. You can also get to
TextEdit through the Finder, by going to “Applications” and clicking on “TextEdit.”
When TextEdit first starts, it is acting like a word processor, not a text editor. If you are
in TextEdit, and it has a formatting bar (with buttons to do bold, italic, etc.), you are in
the wrong mode. When opening text files with TextEdit, be sure to check the “Ignore Rich
Text Commands” checkbox in order to open the file as a text file. If you get the formatting
bar, you are in the wrong mode, and you must close and reopen the file.
When creating new files with TextEdit, you can easily switch from word processing
mode to text editing mode if it starts you in the wrong mode. Just click on the “Format”
menu, and then click “Make Plain Text.” Your document will now be treated as a text
document. You can perform this action anytime before your first save without causing
problems.
You can also set TextEdit to do text editing by default. To do that, go into the
“TextEdit” menu, and then click “Preferences.” Under the “New Document” tab, set the
format to be “Plain Text.” Under the “Open and Save” tab, check the checkbox that says
“Display HTML files as HTML code instead of formatted text.”
When you save files, be sure to set the file extension appropriately. Use .html for
HTML files, .css For CSS files, and .js for JavaScript files. Also note that to open a text
file, be sure to open up TextEdit first, and then open the file. Double-clicking the file itself
may open it up in some other application, such as your browser.
300
Appendix B Operating System and Browser Specifics
301
Appendix B Operating System and Browser Specifics
302
Appendix B Operating System and Browser Specifics
303
Appendix B Operating System and Browser Specifics
alert("Hello");
This will open up an alert window on the page. Any valid JavaScript can be entered
here. It’s great for doing simple experiments or playing around with a web page.
304
Appendix B Operating System and Browser Specifics
305
Appendix B Operating System and Browser Specifics
There are other tabs as well, but these are the ones you will be interacting with the
most as you learn to work with web pages.
306
Appendix B Operating System and Browser Specifics
1. Did you save your file as a text file with the proper extension? If
your text editor has a formatting toolbar (with bold, italic, etc.),
you are probably not saving your file as a text file. Convert your
file to text mode and then save it (see Section B.3). Also be sure
that you have file extensions turned on (see Section B.3.1). If file
extensions are off, even if you specify a file extension, it will add a
new, hidden file extension that you don’t want.
2. Did you type in the program correctly? Computer programs are very
sensitive, and every character matters. Changing one little character
can be the difference between a successful and an unsuccessful
program. Did you put in semicolons, or did you accidentally type a
colon instead? Did you misspell a variable name somewhere? Did
you get both the opening brace and the closing brace? Any mistake
like this will cost you your entire program. Check carefully. After a
while, it becomes second nature. I can now look at a page of code
and spot such errors immediately. That comes with experience—for
now, you have to hunt and check everything.
3. Did your text editor substitute in curly quotes for your regular
quotes? Some text editors think you are typing a document and
want to make your text fancy. When you type in a regular double-
quote ("), they will auto-substitute curly quotes (“). This causes
programming languages to go bonkers because they are very
definite about the characters they are looking for. If your text
editor is doing this, see Section B.3.5.
307
Appendix B Operating System and Browser Specifics
308
APPENDIX C
The JavaScript Toolbox
on Docker
Before reading this appendix, be sure you know how to access the command line (details
provided in Appendix B.2). The information in this appendix applies primarily to
performing the examples in Chapter 3. The problem is that, to perform those exercises,
you need your computer set up in a certain way.
In order to avoid having to get your computer set up in a specific way, we are going
to instead use a tool called Docker to essentially download a small but complete,
configured operating system to your computer and then run the commands inside
that operating system. That way installing these tools has minimal impact on your
system, but the tools work exactly as expected since they are running in their own mini-
operating system.
Note that, since all of this is just for the examples in Chapter 3, you can also feel free
to ignore this appendix and simply imagine those examples working. It’s not as fun, but if
you are having headaches installing everything, it might be worthwhile to skip it instead.
In order to get started, you first need to download and install Docker from docker.
com. While there is a paid version of Docker available, you do not need any paid features
for the examples in this book. Note that, on Windows, depending on your version,
Docker may ask you to do some special configurations to get it up and running. Simply
follow the instructions that it gives you during installation.
Once Docker is up-and-running, you can go to your command line (see Appendix
B.2) and start using it. I have a computer image that is already set up to run the examples
in Chapter 3. To start using it, simply run the following command:
309
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4
Appendix C The JavaScript Toolbox on Docker
The first time you run this, it will start by transferring the operating system image
from Docker Hub. After that, it will start a new virtual computer running this operating
system (known in the Docker world as a container). It will give you a prompt that looks
something like this:
root@5f166a25178a:/#
From here, you can type in the commands given in Chapter 3, and they should work
correctly. Type exit on a line by itself to exit the container, or just close the window.
For more information about Docker and containers, see my book Cloud Native
Applications with Docker and Kubernetes.
310
APPENDIX D
Character Encoding
Issues
D.1 A Short History of Character Encodings
In computer programming, the problem of how to represent character strings (i.e.,
lines of text) is an ever-present issue. Generally, a string of characters is represented
by an array of numbers, where each number represents one character (letter, digit,
punctuation mark, etc.) of text. The problem then becomes a question of which numbers
represent which characters. If every program had its own way of converting numbers
to characters, it would be nearly impossible for two programs to communicate. If
one program used the number 6 to mean the letter F, but another program used 6 to
represent a comma, trying to get those two programs to talk to each other would require
code to translate the number from one system to another, which would be a lot of work.
In addition, if every programmer had to solve this problem for their own program, that
would take a lot of effort for every program that deals with character strings (which is
basically every program).
Therefore, early on in computer programming, standards were developed for
representing character strings. Not only was ASCII developed early in computing, but
the standards were already in place before computers existed, thanks to telegraph
lines. The telegraph was a machine used in the 1800s and early 1900s for sending and
receiving messages over long distances. It worked by sending short and long pulses over
long wires. If you see Morse code printed out, it usually uses dots for the short pulses
and dashes for the long pulses. For instance, the letter A is represented as .- in Morse
code, and the letter X is represented as -..-. In Morse code, the more common letters
have shorter codes, and the less common letters have longer codes, making it easier for a
telegraph operator to type messages.
311
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4
Appendix D Character Encoding Issues
312
Appendix D Character Encoding Issues
programs which wanted to support users from every country. If your document only
used English characters, it was identical whether it was encoded in ASCII or UTF-8. The
differences only came when you ventured into other character sets. UTF-8 is less efficient
for processing, but its ability to interoperate with older programs has made it the default
in many applications. JavaScript uses UTF-8 for its encodings by default.
0 00 000 <null>
9 09 011 <tab>
10 0a 012 <line feed>
13 0d 015 <carriage return>
30 1e 036 <record separator>
31 1f 037 <field separator>
32 20 040 <space>
33 21 041 !
34 22 042 "
35 23 043 #
36 24 044 $
37 25 045 %
(continued)
313
Appendix D Character Encoding Issues
38 26 046 &
39 27 047 ’
40 28 050 (
41 29 051 )
42 2a 052 *
43 2b 053 +
44 2c 054 ,
45 2d 055 -
46 2e 056 .
47 2f 057 /
48 30 060 0
49 31 061 1
50 32 062 2
51 33 063 3
52 34 064 4
53 35 065 5
54 36 066 6
55 37 067 7
56 38 070 8
57 39 071 9
58 3a 072 :
59 3b 073 ;
60 3c 074 <
61 3d 075 =
62 3e 076 >
63 3f 077 ?
(continued)
314
Appendix D Character Encoding Issues
64 40 100 @
65 41 101 A
66 42 102 B
67 43 103 C
68 44 104 D
69 45 105 E
70 46 106 F
71 47 107 G
72 48 110 H
73 49 111 I
74 4a 112 J
75 4b 113 K
76 4c 114 L
77 4d 115 M
78 4e 116 N
79 4f 117 O
80 50 120 P
81 51 121 Q
82 52 122 R
83 53 123 S
84 54 124 T
85 55 125 U
86 56 126 V
87 57 127 W
88 58 130 X
89 59 131 Y
(continued)
315
Appendix D Character Encoding Issues
90 5a 132 Z
91 5b 133 [
92 5c 134 \
93 5d 135 ]
94 5e 136 ^
95 5f 137 _
96 60 140 `
97 61 141 a
98 62 142 b
99 63 143 c
100 64 144 d
101 65 145 e
102 66 146 f
103 67 147 g
104 68 150 h
105 69 151 i
106 6a 152 j
107 6b 153 k
108 6c 154 l
109 6d 155 m
110 6e 156 n
111 6f 157 o
112 70 160 p
113 71 161 q
114 72 162 r
115 73 163 s
(continued)
316
Appendix D Character Encoding Issues
116 74 164 t
117 75 165 u
118 76 166 v
119 77 167 w
120 78 170 x
121 79 171 y
122 7a 172 z
123 7b 173 {
124 7c 174 |
125 7d 175 }
126 7e 176 ˜
317
APPENDIX E
Additional Machine
Language Programs
If you enjoyed the machine programs in Chapter 5, this appendix has a few others you
can try. If you are really brave, you can even try to write one of your own!
This program stores the first number in register 0 and the second number in register 1.
The program works by repeatedly adding the number in register 0 the number of times
specified in register 1. Register 2 holds the results so far, and register 3 holds the number
319
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4
Appendix E Additional Machine Language Programs
of times we have performed the addition so far. Register 4 is used for holding comparison
values. Register 5 holds the number 1 so we can add it to register 3 after each repetition.
320
Appendix E Additional Machine Language Programs
Figure E-3. Machine Language Program to Display the ASCII Code of a Number
though, are limitless, though your imaginations will probably require more than an 8x8
grid for memory.
If you enjoy this sort of programming, you would probably enjoy assembly language
programming, which is similar to machine language except that instead of writing out
the number of the opcodes, you would write out an abbreviated opcode name instead.
My book, Learn to Program with Assembly Language, gives a broad overview of assembly
language programming on modern computers and shows how various programming
language techniques are implemented at the lowest level. In addition, while the machine
language we are dealing with here was invented as a learning tool, Learn to Program
with Assembly Language covers a real machine—the x86-64 family of processors.
While most programmers never need to program in machine language anymore, my
hope is that doing these exercises will have accustomed your mind to the computer’s
way of thinking, which will help you be a better programmer in any programming
language.
322
Index
A Arithmetic opcodes, 62
ARPANET, 13
Absolute path, 79
Arrays, 37
Absolute URL, 79, 80
elements, 151
alert function, 111, 114
index numbers, 151
alert() messages, 307
JavaScript, 150
Altair, 12
largest_age function, 153
Anchor, 23
largest value, 152
Anonymous functions, 205–206
mixing objects, 154–156
appendChild method, 165, 166, 174
ordered sequences of values, 150
Apple I, 12
products, 160
Application frameworks, 241, 246
programs, 151–154
Application-layer protocols, 22, 23
sequences of data, 159
Application programmer, 22
Arrow functions, 226, 227
Application programming
Artificial intelligence, 10
interface (API), 173, 175
ASCII codes, 38, 311, 313, 320, 321
access network, JavaScript, 232, 233
ASCII system, 312
APIKEY, 230
Assembly language
CORS, 238, 240
programming, 322
DELETE, 237
Assignment statements, 109, 130
entity body/payload, 237
expression, 122
GET, 237
functions, 122
HTTP, 229, 237, 239
sample, 121
interaction, web page, 235, 236
variable, 121
JSON, 231, 232, 239
Associative arrays, 225
NASA API, 229, 230, 239
Astronomy Picture of the Day, 229, 230,
POST, 237
232, 233, 235, 240
PUT, 237
Astronomy Picture of the Day Query Tool,
query string, 233, 234
235, 236
Arguments, 226
Attributes, 75, 76, 85–87, 89, 95, 96, 108,
Arithmetic and logic unit (ALU),
149, 163, 217
46–49, 54, 61
Automated telegraph, 312
Arithmetic and Logic Unit sheet, 49, 52, 54
323
© Jonathan Bartlett 2023
J. Bartlett, Programming for Absolute Beginners, https://doi.org/10.1007/978-1-4842-8751-4
INDEX
324
INDEX
325
INDEX
326
INDEX
G hyperlinks, 69
manuscripts, 70
Genesis, 127, 128
markup language, 69
getElementById method, 163, 165, 174
syntax, 86
get_square_a_number_function, 198
tags, 71, 91
Google Chrome, 3, 242
HyperText Transfer Protocol (HTTP), 229,
Groupware services, 13
237, 239, 240
application-level protocol, 29
H blank line, 25
Hashtables, 225 data transmission, 24
Header line, 24 documents, 22
Helv 12, 70 header line, 24
Hexadecimal digit, 34 HTML, 22
Hexadecimal numbers, 34 http object, 243
Hexadecimal system, 33 POST method, 237
Higher-order functions, 197, 204, 207 protocol, 26, 27, 30
Hosting service, 245 request headers, 24
Hostname, 23, 24, 27–29 request line, 24
HTTPS, 26, 27, 29, 229, 244, 245 URL, 23
HyperText Markup Language (HTML), 22, verb, 24
25, 231, 235, 236, 240
attributes, 76
code, 91
I
comment, 86 IBM, 11, 12, 312
content, 102 Identifiers, 120–122, 130
documents, 72–74, 76, 77, 89, 91 if statement
doctype declaration, 87, 88 basic form, 123
elements, 102, 167 blocks, 123
extension, 72 boolean expressions, 126
features boolean value, 124
attributes, 85, 86 code, 124
entities, 81, 82 conditional branching, 123
form tags, 84, 85 conditional expressions, 124
lists, 82 conditions, 125
syntax, 86 ! operator, 126
table tags, 82, 83 Image URL finding, 306
files, 43, 89 Immediate mode, 49, 61
fragments, 75 Immediate operands, 61
327
INDEX
328
INDEX
329
INDEX
330
INDEX
Parameters Q
function parameters, 109, 114, 212
Query string, 23, 233–237, 239
multiple function parameters, 114
search parameters, 233
Parent directory, 81 R
parseInt function, 110, 114, 123, 168 Rails framework, 242
Parsing, 110 React/JQuery, 249
Pop method, 158 Records, 28, 37, 43, 209
Powered machinery, 8 Recursive functions, 192
Powered machines, 7 base case, 189
powershell.exe, 296 definition, 188
Power source, 7 inductive case, 189
Power technology, 14 stack frame, 191
Processing instruction, 86–88 sum_range function, 188–190
Processors, 44, 46, 63, 76, 87, 322 Redirect response, 26
Programming languages, 241, 242 Refactoring, 92, 93, 101
choice, 2 Register mode, 49
JavaScript (see JavaScript) Register operand, 61
machine language, 45, 46 Registers, 47, 49, 52, 55, 57–61, 230,
principles, 2 245, 319
programmers, 1 Relative URLs, 79–81, 89, 113
types, 1 Request headers, 24, 25
Program stack Request routing, 244, 246
built-in function call, 182 Reserved words, 120
code, 182 Response line, 25, 26, 40
function_one function, 180, 181 Responsive layouts, 101
function_three, 180, 182 Return value, 114, 147, 182, 184
function_two, 180, 182 Rich Text Format (RTF), 42, 44
global variable, 179 Root tag, 73
local variables, 179 Router, 19
programming language, 180 .rtf file, 42, 44
Promise, 232, 233, 239
prompt function, 109, 110, 114, 166
Protocol S
definition, 17 Search engines, 308
layers, 18, 19 Secure Sockets Layer (SSL), 22, 245
return address, 18 Self-closing tag, 73, 77, 84
Push method, 157, 158 Sentinel value, 37–39, 42, 43, 56–58
331
INDEX
332
INDEX
333