In the last chapter, we worked with numbers. In this chapter, we’ll work with text and write our first applications.
Go to the GitHub repository learning-web-dev-code
and follow the instructions there.
A data type is the set of all values that are “similar” (of the same kind). So far, we have encountered two data types:
8
, 1.5
, etc.(x) => {return x}
etc.Strings are yet another data type: A string is text – a sequence of zero or more characters (textual symbols). These characters are mentioned in quotes – we can use either single quotes or double quotes:
'A string'
"Also a string"
Strings can be empty (contain zero characters):
''
""
It is interesting to observe that the following two expressions have different syntax but produce the same result:
'abc'
"abc"
That is similar to something we have encountered before: The following two numbers are also syntactically different but create the same value:
123.0
123
+
We can store strings in variables and join them together via the plus operator +
:
> let str = '';
> str = str + 'How are';
> str = str + ' you?';
> str
'How are you?'
Functions can also return strings:
const sayHello = (name) => {
return 'Hello ' + name + '!';
};
We can copy the previous multi-line code to a console and try out how the function works:
> sayHello('Terry')
'Hello Terry!'
In JavaScript, variables can be nested: A variable can itself contain variables. We’ll learn how to do that ourselves in a future chapter. But JavaScript already has many predefined nested variables – e.g. variable Math
contains a variable PI
whose value is a number:
> Math.PI
3.141592653589793
The dot (.
) is used as a separator when accessing nested variables. That is similar to how slashes (/
) or backslashes (\
) separate directory names in file paths. JavaScript uses the following terms:
Math
is a container for variables. Such a container is called an object.PI
is called a property of Math
.Properties can also contain functions and we can call those functions – e.g.:
> Math.sqrt(9)
3
The property Math.sqrt
contains a function that computes the square root of a number. A property whose value is a function is also called a method.
Some methods are aware of their container and derive a result from its contents – e.g.:
> 'hello'.toUpperCase()
'HELLO'
log-hello.html
Let’s move on from the browser console to an actual web app: Roughly, a web app is a web page with an embedded program. (There are many other valid definitions of what a web app is; but this one will be good enough for us – for now.)
The following HTML code contains JavaScript code:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Log hello</title>
</head>
<body>
<script type="module">
···
</script>
</body>
</html>
What do all these HTML tags mean?
<script>
, all of these HTML elements are a normal part of a minimal HTML “skeleton”.<script>
contains the JavaScript code.
type="module"
means that this is actually a small JavaScript module. What exactly that means is not important yet. You can think of it as a modern unit/chunk of code: Modules were added to JavaScript relatively late and have features that were not built into the language before that. They are often stored in extra files (one module per file).<script>
contains the following JavaScript code:
const sayHello = (name) => {
return 'Hello ' + name + '!';
};
const message = sayHelloTo('Terry');
// Log value of `message` to console:
console.log(message);
Only the last two lines do something new.
The second-to-last line is a comment:
// Log value of `message` to console:
Whenever a double slash (//
) appears in code, JavaScript ignores it and everything that comes after it – until the end of the line. Why is that useful? It lets us add explanations for humans so that they understand the code better: Code is written for humans first, computers second.
console.log()
In the last line, we log the value of the variable message
to the console:
console.log(message);
The global object console
has a method .log()
that shows values in the console. If you open the file log-hello.html
in a web browser, you can see this message in the console:
Hello Terry!
log-clicks.html
Let’s say we have an HTML page with the following <body>
:
<a id="link" href="">Click here</a>
This is an empty link: href=""
is only necessary because the link isn’t clickable otherwise. We’d like to run JavaScript code every time the user clicks on this link. We can achieve that as follows:
let count = 1;
const link = document.querySelector('#link');
link.addEventListener(
'click',
(event) => {
event.preventDefault(); // (A)
console.log('Click ' + count); // (B)
count = count + 1;
}
);
Note: // (A)
etc. give “names” to lines. Since they are comments, JavaScript ignores them. Once again, this is information for humans, not for the computer.
In line 2, we retrieve the JavaScript object for the HTML element whose HTML ID is link
. The hash symbol (#
) before link
is CSS syntax for HTML IDs. Now that we have that link object, we can do stuff with it: In line 3, we add an event listener to link
:
An event is something that happens once, regularly or irregularly. There are many kinds of events: the user clicks, the user presses a key, etc. In this case, we are interested in mouse clicks (and finger taps) which is why the first argument of the method call link.addEventListener()
is 'click'
. The second argument is a function that is called every time the user clicks on link
. That function is called an event listener
If an <a>
element has an href
attribute, clicking on it jumps to the address specified by href
. We don’t want that to happen, so we prevent it in line A, via event.preventDefault()
– which, as the name implies, prevents the web browser from performing the default action.
Note that the variable count
is created in line 1 – outside the event listener. That’s why its value is preserved between invocations of that function: Variables declared inside a function are created fresh every time it is called.
You can now open log-clicks.html
in your browser and see how it works. You need to open the browser console to see the output produced in line B.
123 vs. '123'
? Now that we know both numbers and strings: What is the difference between the following two values?
123
'123'
123
is a number: We can perform arithmetic with it etc.'123'
is a string: We can concatenate it with other strings etc.The difference is similar to the difference between a dog and a photo of a dog: The photo looks like a dog, but you can’t play fetch with it etc. Similarly, the string '123'
looks like a number but is not a number.
JavaScript has a function String()
that converts numbers to strings:
> String(123)
'123'
It also has a function Number()
that converts strings to numbers:
> Number('123')
123
Additionally, the plus operator (+
) converts a number to a string if the other operand is a string – e.g.:
> 1 + 'X'
'1X'
> 'X' + 1
'X1'
> 'I bought ' + 3 + ' apples'
'I bought 3 apples'
display-clicks.html
So far, we have used the console to display status information. However, we can’t expect normal users to open the console to see that information – the console is only meant for developers. Let’s display the status information right on the web page.
The HTML specifies how the user interface looks at the beginning (its initial state):
<div>
<a id="link" href="">Click here</a>
</div>
<div>
Number of clicks: <span id="clickCount">0</span>
</div>
We once again react to clicks via an event listener:
const link = document.querySelector('#link');
const clickCount = document.querySelector('#clickCount'); // (A)
let count = 1;
link.addEventListener(
'click',
(event) => {
event.preventDefault();
clickCount.innerText = String(count); // (B)
count = count + 1;
}
);
Explanation:
'clickCount'
.count
to the console, we convert it to a string and store it in the property .innerText
of the HTML element clickCount
. This special property changes the content of the HTML element.You can open display-clicks.html
to see this web app in action.
temperature-converter.html
temperature-converter.html
is an app that converts temperatures from degree Celsius to degree Fahrenheit: It has two text fields. If we enter a number in one of them, it shows the correct analog in the other one. Let’s see how that works for the Celsius text field – the code for Fahrenheit is similar.
This is the HTML for the text field:
<label>
Celsius: <input id="celsius" type="text" size="10">
</label>
This is the JavaScript code:
const celsius = document.querySelector('#celsius');
const fahrenheit = document.querySelector('#fahrenheit');
const celsiusToFahrenheit = (c) => {
return (c * (9/5)) + 32;
};
celsius.addEventListener( // (A)
'change',
() => {
const c = Number(celsius.value); // (B)
fahrenheit.value = String(celsiusToFahrenheit(c)); // (C)
}
);
In line A, we once again use an event listener. This time, we listen to change events: They are triggered by pressing Return while inside a text field and by clicking outside a text field – so that the text cursor inside it disappears.
Whenever there is a change (line B):
celsius.value
to retrieve the content of the text field celsius
as a string.Number()
andc
.In line C:
c
to Fahrenheit.fahrenheit
text field so that it is displayed in the user interface.So, the special property .value
of text field HTML elements can be used in two ways:
temperature-converter.html
so that it converts currencies (e.g. between USD and EUR).