For statements
In the first module of the course we mostly discussed interaction with single entities, like greeting a single user or calculating the discounted price of an item. Very often we'll have to deal with homogenous collection of entities, e.g.:
- the results for a given search term;
- the users that like a post;
- the books a user has read.
We want to perform actions on them regardless of how many items are in the collection.
Imagine having the following scenario:
function rateBook(book) { console.log(book.title, 'by', book.author); if (book.rating < 5) { console.log("It really wasn't a good read"); } else if (book.rating < 8) { console.log("I found it pretty good"); } else { console.log("It was really awesome!"); } } const firstBook = { title: 'The da Vinci Code', author: 'Dan Brown', rating: 4 }; const secondBook = { title: 'Fever Pitch', author: 'Nick Hornby', rating: 6 }; const thirdBook = { title: 'Ask the Dust', author: 'John Fante', rating: 9 }; rateBook(firstBook); rateBook(secondBook); rateBook(thirdBook);
Toggle Console Output
- The da Vinci Code by Dan Brown
- It really wasn't a good read
- Fever Pitch by Nick Hornby
- I found it pretty good
- Ask the Dust by John Fante
- It was really awesome!
That's a lot of repeated calls to rateBook, and there is no hint in the code that the three books should belong together. In the next lesson we'll introduce a very useful data structure that will address this specific problem, but first we' have to get good with its companion tool.
Repeated operations
There two main tools that can translate most of the problems into code. We have already seen the if statement used to make decisions, and now we'll see another whose purpose is to repeat a set of operations:
for (let i = 0; i < 3; i++) { console.log("All work and no play may make Jim a dull boy"); }
Toggle Console Output
- All work and no play may make Jim a dull boy
- All work and no play may make Jim a dull boy
- All work and no play may make Jim a dull boy
That quite some new syntax all at once, but let's observe the output. We have three times the same log statement, and there is a number 3 in the code. It may as well be a coincidence, so let's try to change that quantity:
for (let i = 0; i < 4; i++) { console.log("All work and no play may make Jim a dull boy"); }
Toggle Console Output
- All work and no play may make Jim a dull boy
- All work and no play may make Jim a dull boy
- All work and no play may make Jim a dull boy
- All work and no play may make Jim a dull boy
It looks like the two things are connected. But what's actually happening?
Anatomy of a for statement
The structure we have just seen is a for statement. It is very often also called a for loop, because it makes the code insist on the same portion of the code multiple times. It consist of three expressions separated by semicolons and enclosed in parentheses, followed by a code block in curly brackets:
for ( exp 1; exp 2; exp 3) {
// code block
}
The three expressions are:
- the initialization: it allows the declaration of one or more variables;
- the condition: it's evaluated before the code block, and:
- if evaluates to
true, the code block is executed; - if not, the program moves on to what comes after the for statement;
- if evaluates to
- the afterthought: it is evaluated after the code block.
It's important to know that the block is not even once executed if the condition is never met, same applies for the afterthought.
Let's see what is happening to the variable i:
for (let i = 0; i < 3; i++) { console.log(i); }
Toggle Console Output
- 0
- 1
- 2
We read three logs with three different values. The following things are happening:
- the
ivariable is initialized as 0; - the condition is evaluated, 0 is lesser than 3;
- the value of
iis logged inside the block, we read 0 in the console; - the afterthought is evaluated,
ibecomes0 + 1 = 1.
Second round:
- condition evaluated again, 1 is lesser than 3;
- the block gets executed again. This time
iholds 1 as value; - afterthought,
iis now 2;
Third round:
- condition evaluated yet again, 2 is lesser than 3;
iis logged, yielding 2 in the console;- afterthought,
iis now 3.
Fourth round:
- condition evaluated, 3 is not lesser than itself!
- we move on with the program.
It looks like a lot of considerations, because they are a lot! But we have to do them in depth since it's our first encounter with the syntax. You have to appreciate the transparency of the language. It's crucial that we spend all the time in the world doing these petulant observations now that the program is just logging a variable, before the code gets entangled.
The i variable is declared with let because we need to update it in the afterthought, or better the computer does it for us! It's the power of iteration.
Changing the variable name
We use i as a variable name in a for statement because it stands for index, but you are free to name it as you see fit - just make sure to be consistent:
for (let figaro = 0; figaro < 3; figaro++) { console.log(figaro); }
Toggle Console Output
- 0
- 1
- 2
Feel free to name it explicitly index if it improves your comprehension.
Changing the initial value
You don't have to start from 0 if you don't need to:
for (let i = 1; i < 5; i++) { console.log(i); }
Toggle Console Output
- 1
- 2
- 3
- 4
Changing the condition check
You don't have to check just for strict lesser than:
for (let i = 0; i <= 3; i++) { console.log(i); }
Toggle Console Output
- 0
- 1
- 2
- 3
This time we have four logs, because 3 satisfied the condition - <= vs <.
Changing the afterthought
You have freedom here as well:
for (let i = 0; i < 3; i = i + 0.5) { console.log(i); }
Toggle Console Output
- 0
- 0.5
- 1
- 1.5
- 2
- 2.5
In this case we wanted a different increment, that's why we used an explicit assignation and not the increment operator.
Printing a list of numbers
Let's write a function now that prints all integer numbers from a given start to a given end, both included:
function printNumbers(start, end) { for (let i = start; i <= end; i++) { console.log(i); } } printNumbers(1, 5);
Toggle Console Output
- 1
- 2
- 3
- 4
- 5
It works! Important to notice:
- the
iis initialized to the value of the passedstartparameter; - the check is made against the value of the
endparameter; - the
endvalue satisfies the check due to the lesser than or equals -<=.
Conclusion
We have seen a lot of information. You don't have to digest all at once, especially because we'll see that there are more idiomatic ways to perform the same operations in JavaScript. It's enough to have the idea that operations can be repeated a controlled number of times.