This blog post is part of the series “Learning web development” – which teaches people who have never programmed before how to create web apps with JavaScript.
To download the examples, go to the GitHub repository learning-web-dev-code
and follow the instructions there.
I’m interested in feedback! If there is something you don’t understand, please write a comment at the end of this page.
In this chapter we look at one way of storing more than one value in a variable: arrays.
If the values we have encountered so far (numbers and strings) are single sheets of paper then an Array is a stack of sheets of paper. Let’s explore how arrays work:
Let’s create an array and assign it to the variable arr
:
> const arr = ['a', 'b', 'c'];
We have created an array that contains three strings. The syntax works as follows:
The syntax for creating an array is called an array literal. We have already seen other kinds of literals:
5
, -2
, 6.1
, etc.'', 'abc'
, etc.How many elements does the array in arr
have?
> arr.length
3
Array elements are accessed via indices – numeric positions that start at zero. We can read elements:
> arr[0]
'a'
And we can write elements:
> arr[0] = 'x';
> arr
[ 'x', 'b', 'c' ]
The index of the last array element is always .length
minus one:
> arr[arr.length - 1]
'c'
const
Why can we change the array if arr
is a const
variable? const
only prevents us from putting different values into the box that is the variable. If the box contains a value that is mutable (can be changed) then const
does not prevent us from changing that value.
Note that numbers, strings and undefined
are all immutable – they can’t be changed, only replaced. For example, the following code does not change the number that’s stored in the variable num
– it puts a new number into the variable:
let num = 0;
num = num + 1;
The //
comment is called a single-line comment because it exists in a single line. There are also multi-line comments: Their ends are marked explicitly and they can span more than one line:
/* Multi-line comment that fits into a single line */
/* Multi-line comment
that spans
three lines */
For aesthetic purposes, multi-line comments are sometimes written as follows. Note that that doesn’t change anything for JavaScript: It still simply ignores what’s between /*
and */
.
/*
* Multi-line comment
* that spans
* five lines
*/
magic-8-ball.html
Let’s implement a Magic 8 Ball app: The user comes up with a yes-no question in their mind. After they push a button, the app displays an answer. The user interface looks as follows in HTML:
<ol>
<li>Ask a yes-no question!</li>
<li><button id="answerButton">Click to show answer</button></li>
</ol>
<p id="answerPlaceholder"></p>
The <p>
in the last line is a blank that we eventually fill with an answer via JavaScript.
This is an abbreviated version of the JavaScript code:
const answers = [
'It is certain',
'It is decidedly so',
// Etc.
];
const answerButton = document.querySelector('#answerButton');
const answerPlaceholder = document.querySelector('#answerPlaceholder');
answerButton.addEventListener(
'click',
() => { // (A)
const answerIndex = getRandomInteger(answers.length);
const answer = answers[answerIndex];
answerPlaceholder.innerText = 'Answer: ' + answer;
}
);
We once again react to click events. With <a>
, we had to call event.preventDefault()
. With <button>
, there is no need to do that because it doesn’t have a default action. Therefore, we don’t need the function parameter event
– which is why the event listener has no parameters (line A).
What does the event listener do?
First, we use the function getRandomInteger
(whose code we’ll see later) to compute an integer value between (including) 0
and (excluding) answers.length
. In other words: answerIndex
is an index that we can use to access an element of the array answers
.
Second, we read an answer from the array answers
.
Third, we display that answer on the HTML page, by assigning a string to the special property .innerText
of the HTML element answerPlaceholder
.
getRandomInteger()
work? This is the code for the function getRandomInteger()
:
/* Returns a random integer i with 0 <= i < max */
const getRandomInteger = (max) => {
return Math.floor(Math.random() * max);
};
Line 1 is a multi-line comment that describes to humans what the function does.
First we use Math.random()
to compute a random number between (including) 0 and (excluding) 1. It other words: The number may be 0
but it is never 1
.
Next, we multiply the random number with the parameter max
. Given that the random number is always smaller than 1
, the result of the multiplication will always be smaller than max
(but it may get very close to it).
The result is not yet an integer. We use Math.floor()
to round it to an integer. It always rounds down – i.e., if we call it with a positive number, it removes any decimal fraction (the digits after the dot) that it may have:
> Math.floor(1.0) // already an integer
1
> Math.floor(1.23456)
1
> Math.floor(1.99999)
1
Let’s go through an example. Let’s assume the parameter max
is 5
:
> const max = 5;
If the result of Math.random()
is close to the upper limit 1, we end up with an integer that’s max
minus one:
> 0.9999 * max
4.9995
> Math.floor(4.9995)
4
If the result of Math.random()
is close to the lower limit 0, we end up with the integer zero:
> 0.0001 * max
0.0005
> Math.floor(0.0005)
0
If Math.random()
returns zero, we end up with the integer zero:
> 0 * max
0
> Math.floor(0)
0
magic-8-ball.html
so that it randomly displays something different – e.g.: