Chapter 2Program Structure

And my heart glows bright red under my filmy, translucent skin and they have to administer 10cc of JavaScript to get me to come back. (I respond well to toxins in the blood.) Man, that stuff will kick the peaches right out your gills!

_why, Why's (Poignant) Guide to Ruby
Picture of tentacles holding objects

In this chapter, we will start to do things that can actually be called programming. We will expand our command of the JavaScript language beyond the nouns and sentence fragments we’ve seen so far, to the point where we can express meaningful prose.

2.1

Expressions and statements

In Chapter 1, we made values and applied operators to them to get new values. Creating values like this is the main substance of any JavaScript program. But that substance has to be framed in a larger structure to be useful. So that’s what we’ll cover next.

A fragment of code that produces a value is called an expression. Every value that is written literally (such as 22 or "psychoanalysis") is an expression. An expression between parentheses is also an expression, as is a binary operator applied to two expressions or a unary operator applied to one.

This shows part of the beauty of a language-based interface. Expressions can contain other expressions in a way similar to how subsentences in human languages are nested—a subsentence can contain its own subsentences, and so on. This allows us to build expressions that describe arbitrarily complex computations.

If an expression corresponds to a sentence fragment, a JavaScript statement corresponds to a full sentence. A program is a list of statements.

The simplest kind of statement is an expression with a semicolon after it. This is a program:

1;
!false;

It is a useless program, though. An expression can be content to just produce a value, which can then be used by the enclosing code. A statement stands on its own, so it amounts to something only if it affects the world. It could display something on the screen—that counts as changing the world—or it could change the internal state of the machine in a way that will affect the statements that come after it. These changes are called side effects. The statements in the previous example just produce the values 1 and true and then immediately throw them away. This leaves no impression on the world at all. When you run this program, nothing observable happens.

In some cases, JavaScript allows you to omit the semicolon at the end of a statement. In other cases, it has to be there, or the next line will be treated as part of the same statement. The rules for when it can be safely omitted are somewhat complex and error-prone. So in this book, every statement that needs a semicolon will always get one. I recommend you do the same, at least until you’ve learned more about the subtleties of missing semicolons.

2.2

Bindings

How does a program keep an internal state? How does it remember things? We have seen how to produce new values from old values, but this does not change the old values, and the new value has to be immediately used or it will dissipate again. To catch and hold values, JavaScript provides a thing called a binding, or variable:

let caught = 5 * 5;

That’s a second kind of statement. The special word (keyword) let indicates that this sentence is going to define a binding. It is followed by the name of the binding and, if we want to immediately give it a value, by an = operator and an expression.

The previous statement creates a binding called caught and uses it to grab hold of the number that is produced by multiplying 5 by 5.

After a binding has been defined, its name can be used as an expression. The value of such an expression is the value the binding currently holds. Here’s an example:

let ten = 10;
console.log(ten * ten);
// → 100

When a binding points at a value, that does not mean it is tied to that value forever. The = operator can be used at any time on existing bindings to disconnect them from their current value and have them point to a new one.

let mood = "light";
console.log(mood);
// → light
mood = "dark";
console.log(mood);
// → dark

You should imagine bindings as tentacles, rather than boxes. They do not contain values doos-metafoorBij DWA gebruiken we juist wel de doos-metafoor en we kunnen ons voorstellen dat de waarde in een doos zit. De naam van de binding kunnen we ons voorstellen als het label dat op die doos staat.; they grasp them—two bindings can refer to the same value. A program can access only the values that it still has a reference to. When you need to remember something, you grow a tentacle to hold on to it or you reattach one of your existing tentacles to it.

Bij DWA gebruiken we de doos-metafoor voor alle primitieven:

Zie ook JavaScript data types and data structures uit de MDN web docs voor een overzicht en beschrijving van de datatypes in JavaScript.

Let’s look at another example. To remember the number of dollars that Luigi still owes you, you create a binding. And then when he pays back $35, you give this binding a new value.

let luigisDebt = 140;
luigisDebt = luigisDebt - 35;
console.log(luigisDebt);
// → 105

When you define a binding without giving it a value, the tentacle has nothing to grasp, so it ends in thin air. If you ask for the value of an empty binding, you’ll get the value undefined.

Bij DWA gebruiken we ook geheugenmodellen om de huidige toestand van het programma weer te geven. We kunnen ons voorstellen dat de JavaScript runtime (Node.js, of de Browser) een lijst van alle variabelen bijhoudt met de bijbehorende waarde.

Als de runtime net regel 1 heeft uitgevoerd van bovenstaand programma, dan ziet het geheugenmodel er zo uit:

En na regel 2 is dit het geheugenmodel:

Het geheugenmodel wordt in de loop van de tekst verder uitgebreid.

A single let statement may define multiple bindings. The definitions must be separated by commas.

let one = 1, two = 2;
console.log(one + two);
// → 3

The words var and const can also be used to create bindings, in a way similar to let.

var name = "Ayda";
const greeting = "Hello ";
console.log(greeting + name);
// → Hello Ayda

The first, var (short for “variable”), is the way bindings were declared in pre-2015 JavaScript. I’ll get back to the precise way it differs from let in the next chapter. For now, remember that it mostly does the same thing, but we’ll rarely use it in this book because it has some confusing properties.

The word const stands for constant. It defines a constant binding, which points at the same value for as long as it lives. This is useful for bindings that give a name to a value so that you can easily refer to it later.

Het geheugenmodel van bovenstaand programma nadat regel 2 is uitgevoerd, ziet er zo uit:

Het woord ‘binding’ komt je misschien wat minder bekent voor dan het woord ‘variabele’, maar in deze tekst word altijd het woord ‘binding’ gebruikt. ‘Binding’ is een wat exacter woord voor een koppeling tussen een naam en een waarde dan een ‘variabele’. Strikt genomen is een const bijvoorbeeld geen variabele, maar wel een binding (hoewel je vaak genoeg mensen hoort spreken van een ‘constante variabele’).

2.3

Binding names

Binding names can be any word. Digits can be part of binding names—catch22 is a valid name, for example—but the name must not start with a digit. A binding name may include dollar signs ($) or underscores (_) but no other punctuation or special characters.

Words with a special meaning, such as let, are keywords, and they may not be used as binding names. There are also a number of words that are “reserved for use” in future versions of JavaScript, which also can’t be used as binding names. The full list of keywords and reserved words is rather long.

break case catch class const continue debugger default
delete do else enum export extends false finally for
function if implements import interface in instanceof let
new package private protected public return static super
switch this throw true try typeof var void while with yield

Don’t worry about memorizing this list. When creating a binding produces an unexpected syntax error, see whether you’re trying to define a reserved word.

Oefening 2.3.1: Is Name Allowed

Bekijk onderstaand programma. Geef per regel aan of de binding declaratie in dit programma is toegestaan, of niet.

let $;
let __school;
let ica;
var han;
let _undefined;
var han; //Declaratie van een bestaande binding
let x_*_y;
let let$;
let class_22;
let x&y;
let _;
let ica; //Declaratie van een bestaande binding
2.4

The environment

The collection of bindings and their values that exist at a given time is called the environment. When a program starts up, this environment is not empty. It always contains bindings that are part of the language standard, and most of the time, it also has bindings that provide ways to interact with the surrounding system. For example, in a browser, there are functions to interact with the currently loaded website and to read mouse and keyboard input.

2.5

Functions

A lot of the values provided in the default environment have the type function. A function is a piece of program wrapped in a value. Such values can be applied in order to run the wrapped program. For example, in a browser environment, the binding prompt holds a function that shows a little dialog box asking for user input. It is used like this:

prompt("Enter passcode");
A prompt dialog

Executing a function is called invoking, calling, or applying it. You can call a function by putting parentheses after an expression that produces a function value. Usually you’ll directly use the name of the binding that holds the function. The values between the parentheses are given to the program inside the function. In the example, the prompt function uses the string that we give it as the text to show in the dialog box. Values given to functions are called arguments. Different functions might need a different number or different types of arguments.

The prompt function isn’t used much in modern web programming, mostly because you have no control over the way the resulting dialog looks, but can be helpful in toy programs and experiments.

2.6

The console.log function

In the examples, I used console.log to output values. Most JavaScript systems (including all modern web browsers and Node.js) provide a console.log function that writes out its arguments to some text output device. In browsers, the output lands in the JavaScript console. This part of the browser interface is hidden by default, but most browsers open it when you press F12 or, on a Mac, command-option-I. If that does not work, search through the menus for an item named Developer Tools or similar.

In de loop der jaren is de MDN web docs een gezaghebbende bron geworden voor de API documentatie van JavaScript. Zie hier: JavaScript op MDN.

Node.js heeft zijn eigen API documentatie en die kun je hier vinden Node.js API.

When running the examples (or your own code) on the pages of this book, console.log output will be shown after the example, instead of in the browser’s JavaScript console.

let x = 30;
console.log("the value of x is", x);
// → the value of x is 30

Though binding names cannot contain period characters, console.log does have one. This is because console.log isn’t a simple binding. It is actually an expression that retrieves the log property from the value held by the console binding. We’ll find out exactly what this means in Chapter 4.

Controle structuren (if, while, for, switch, etc), ++, +=, naamgevings- en layoutconventies en kommentaar (// /* */) in JavaScript en Java zijn gelijk.

De volgende, grijze tekst hoef je niet te lezen.
Lees verder waar de tekst weer zwart-op-wit wordt.
einde van tekst die overgeslagen kan worden
2.18

Summary

You now know that a program is built out of statements, which themselves sometimes contain more statements. Statements tend to contain expressions, which themselves can be built out of smaller expressions.

Putting statements after one another gives you a program that is executed from top to bottom. You can introduce disturbances in the flow of control by using conditional (if, else, and switch) and looping (while, do, and for) statements.

Bindings can be used to file pieces of data under a name, and they are useful for tracking state in your program. The environment is the set of bindings that are defined. JavaScript systems always put a number of useful standard bindings into your environment.

Functions are special values that encapsulate a piece of program. You can invoke them by writing functionName(argument1, argument2). Such a function call is an expression and may produce a value.

De volgende, grijze tekst hoef je niet te lezen.
Lees verder waar de tekst weer zwart-op-wit wordt.
einde van tekst die overgeslagen kan worden