Jump to content

JavaScript/Loops

From Wikibooks, open books for an open world



JavaScript supports the repetitive execution of code blocks via the keywords for and while. Similar behavior is offered by the forEach method of data type Array (and similar data types).

for (;;) {}

[edit | edit source]

The syntax of the for statement is: for (<initial expression>; <condition>; <final expression>) { <block> }. It is executed based on the following rules:

  1. The initial expression is executed - exactly once for the complete for statement. Usually, it declares and initiates one or more variables - often numbers with integer values. Sometimes the declaration of the variables is made above the for statement.
  2. The condition is evaluated. If it returns true, step 3 follows. If it returnsfalse, the for statement terminates.
  3. The code block is executed.
  4. The final expression is executed. Usually, it increments or decrements a variable that is part of the condition.
  5. The loop repeats at step 2.
for (let i = 0; i < 10; i++) {
  // a block of statements
}

An example: Show the series of even numbers multiplied by itself (power 2); show the sum over the numbers from 0 to 10.

"use strict";

const upperLimit = 10;
let sum = 0;
let tmpString = "";

for (let i = 0; i <= upperLimit; i++) {
  sum = sum + i;
  if (i % 2 === 0) {
    tmpString += i*i + "; "
  }
}
alert ("The sum is: " + sum + ". The square numbers are: " + tmpString);

Optional syntax parts

[edit | edit source]

The initial expression, the condition, and the final expression are optional. If you omit one or more of them, your script shall perform other useful statements to control the loop. Some examples:

"use strict";

// an infinite loop if you do not terminate it with 'break' (see below)
for (;;) {
  // ...
  break;
}

const answer = prompt("With which start value shall the loop begin?");
let i = Number(answer);
for (; i >= 0 && i < 10; i++) {
  // the start value is computed above the loop
}

for (let i = 0; i < 10; ) {
  // ...
  if (true) { // an arbitrary other condition to control the increment
    i++;
  }
}

Nesting

[edit | edit source]

for loops can be nested. You can use a second (or 'inner') loop within the block of the first (or 'outer') loop.

"use strict";

const maxInner = 10;
const maxOuter = 4;
let myString = "";

for (let o = 1; o <= maxOuter; o++) {
  myString = "";
  // Be careful. It's easy to confuse inner and outer loop variables.
  for (let i = 1; i <= maxInner; i++) {
    myString = myString + o*i + ", ";
  }
  alert(myString);
}

This nesting of loops is also possible in all the below constructs.

continue / break

[edit | edit source]

Sometimes only parts or the block shall run. This can be realized by one or more if / else statements. If it's appropriate, such conditional statements can be shortened by the keyword continue. If continue is reached, the rest of the block is skipped, and the above step 4 final expression is executed.

"use strict";

for (let i = 0; i <= 6; i++) {  
  if (i === 5) { 
    continue;   // skip the rest of the block
  }
  alert(i);     // 0, 1, 2, 3, 4, 6
}

This example is very simple. It skips the lower part of the block for the case where i equals to 5. Of course, it can be expressed differently. A more realistic example would be a loop over the result of a database search which skips parts of a complex handling of rows with a specific status.

The break keyword is similar but more rigid than the continue keyword. It skips not only the rest of the block but also terminates the complete loop.

"use strict";

for (let i = 0; i <= 6; i++) {  
  if (i === 5) { 
    break;      // terminal the loop
  }
  alert(i);     // 0, 1, 2, 3, 4
}

A realistic scenario is a loop over the result of a database search where the connection to the database is broken in the middle of the loop.

You can use continue and break in all forms of the here-discussed variants of loops.

do {} while ()

[edit | edit source]

The syntax of the statement is: do { <block> } while (<condition>). It is executed based on the following rules:

  1. The block is executed. Because this is the very first step, the block is executed at least 1 time. This is helpful if you want to be sure that something happens under all circumstances.
  2. The condition is evaluated. If it returns true, step 1 is invoked again. If it returnsfalse, the loop terminates. Please notice that there is no specific part where you can manipulate a variable that is checked in the condition. This must be done somewhere in the block among the other statements.
"use strict";

let counter = 100;
do {
  counter++;
  alert(counter);  // ... or some logging
} while (counter < 10);

while () {}

[edit | edit source]

The syntax of while (<condition>) { <block> } is very similar to the previous do { <block> } while (<condition>). The only difference is that the condition is checked before and not after the block.

for (x in Object) {}

[edit | edit source]

This language construct is intended to iterate over the properties of an object. Its syntax is: for (<variable> in <object>) { <block> }. The variable receives the key of all properties - one after the next - of the object. For each of them, the block is executed once.

"use strict";

const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};

for (const key in myObj) {
  alert(key); // firstName, familyName, born
  // alert(myObj[key]);  // if you want to see the values
}

Arrays are specialized objects. Hence it is possible to use the for..in on arrays. The keys for arrays are integers starting with 0 - and that is precisely what is extracted from the array.

"use strict";

const myArray = ["certo", "uno", "dos", "tres"];
for (const key in myArray) {
  alert(key); // 0, 1, 2, 3
  // alert(myArray[key]);  // if you want to see the values
}

Arrays also accept non-numeric keys, e.g., myArray["four"] = "cuatro";. The for..in loop handles such non-numeric keys - in opposite to the below for..of loop, and in opposite to the traditional for loop at the top of this page.

See also: MDN: for..in

for (x of Array) {}

[edit | edit source]

This language construct is intended to iterate over an array. Its syntax is: for (<variable> of <iterable object>) { <block> }. The variable receives all values - one after the next - of the array. For each of them, the block is executed once.

This definition sounds similar to the above definition of the for..in. But there are significant differences:

  • It returns the values, not the keys resp. index of the array.
  • It works only on all iterable objects (Array, Map, Set, ...). The data type 'object' is not iterable.
  • It works only on such keys which are numeric. Non-numerical keys resp. index are silently ignored.
"use strict";

const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";

for (const myValue of myArray) {
  alert(myValue); // cero, uno, dos, tres. No 'cuatro' because the key is a string.
}

See also: MDN: for..of

for..in vs. for..of

[edit | edit source]

The differences between the two language constructs are summarized in an example.

"use strict";

const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";

// for..of not allowed on true objects; only for..in is possible.
for (const x of myObj) {};  // error

for (const x in myArray) {
  alert(x); // 0, 1, 2, 3, four
}

for (const x of myArray) {
  alert(x); // cero, uno, dos, tres. NO cuatro!
}

Object.entries() method

[edit | edit source]

If you are looking for a loop that processes both keys and values of an object, there is a more straightforward method than the above-shown combination of the for..in with myObj[key]. The data type Object offers the entries() method that returns an array. Each element of this array contains an array with two values: the property key and the property value. In other words: the return value of the entries() method is a two-dimensional array. And - as usual with arrays - you should use it in combination with for..of.

"use strict";

const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";

for (const [key, val] of Object.entries(myObj)) {
  alert(key + ' / ' + val);
}
for (const [key, val] of Object.entries(myArray)) {
  alert(key + ' / ' + val); // 'four / cuatro' is included
}

Hint: The Object.entries() as well as the following Array.forEach() methods are no 'core' language elements like keywords or the for..in or for..of language constructs. They are methods of the Object respectively Array data type.

Array.forEach() method

[edit | edit source]

The data type Array offers the method forEach(). It loops over the elements of the array, returning one element after the next. The interesting point is that it takes a function as its argument. This makes the difference to the divers for and while loops. Such functions are often called callback function.

The method invocation is very easy: myArray.forEach(myFunction). The - possibly - confusing part is that function calls can be abbreviated in various ways.

The first example shows the function call explicitly. It defines the function myFunction which also takes a single argument. When myFunction is called by forEach(), the next array element is inserted as the argument to myFunction.

"use strict";

// function definition (the function is not called here!)
function myFunction(element) {
  alert("The element of the array is: " + element)
};

// a test array
const myArray = ['a', 'b', 'c'];

// iterate over the array and invoke the function once per array element
myArray.forEach(myFunction);

The following examples show some abbreviations of the function invocation syntax.

"use strict";

// the 'arrow' syntax
const myFunction = 
  (element) => {
    alert("The element of the array is: " + element)
  };

// same code without line breaks:
// const myFunction = (element) => {alert("The element of the array is: " + element)};

const myArray = ['a', 'b', 'c'];
myArray.forEach(myFunction);
"use strict";
const myArray = ['a', 'b', 'c'];

// Define the function directly as the argument of the forEach(). Such
// functions are called 'anonymous' functions.
myArray.forEach((element) => {alert("The element of the array is: " + element)});
"use strict";
const myArray = ['a', 'b', 'c'];

// in simple cases, more syntactical elements are optional
myArray.forEach(element => alert("The element of the array is: " + element));

It depends on your preference, which syntax you use.

In many cases, the called function performs side effects like logging. To calculate values over all array elements, it is necessary to use the technique of closures. In the following example, the variable sum is not defined in the outer context, not in the anonymous function.

"use strict";

const myArray = [3, 0, -1, 2];
let sum = 0;

myArray.forEach(element => sum = sum + element);
alert(sum);

All in all, the following rules apply to the forAll() method:

  • The method can be used for iterable objects like Array, Map, Set. The data type Object is not iterable.
  • The method only iterates over such elements which have a numerical key - what is the usual case for arrays.

See also:

MDN: forEach()
MDN: Iterative methods

Exercises

[edit | edit source]
... are available on another page (click here).

See also

[edit | edit source]