if / else / else if

Il costrutto if(condizione) {istruzioni} serve per eseguire il codice contenuto all'interno delle parentesi graffe solo se la condizione indicata tra parentesi tonde risulta vera. La condizione che determina se eseguire il codice o meno deve essere del tipo che restituisce un valore booleano (un confronto tra due variabili, l'esistenza di una variabile ecc....).

Nel caso in cui la condizione risulti falsa il codice inserito tra parentesi graffe viene semplicemente saltato, oppure ne viene eseguito uno alternativo indicato nel costrutto else {istruzioni}.

E' possibile usare il costrutto else if(condizione) {istruzioni} per indicare una o più altre condizioni da valutare nel caso in cui la prima risulti falsa. La prima delle condizioni else if che risulta vera è quella il cui codice verrà eseguito. Se tutte le condizioni sono false viene eseguito il codice indicato nel costrutto else.

I costrutti if possono anche essere annidati uno dentro l'altro.

var cane = "bau";
var gatto = "miao";
var z = 0;

if (cane == gatto) {
    //il codice qui non viene eseguito perchè "bau" non è uguale a "miao"
}
else { //l'else non è obbligatorio se non serve
    console.log("bau è diverso da miao");
}

if (cane != gatto) console.log("bau è diverso da maio"); //se l'istruzione è di una sola riga si possono omettere le {}

if (cane == gatto || gatto == z) { 
    
}
else if ((gatto.length > 6) && (cane.length == 3)) { //con le parentesi si separano per bene le condizioni 
    //il codice qui non viene eseguito perchè "miao" non è più lunga di 6 caratteri 
}
else if (gatto.charAt(0) == "c") { //si possono mettere uno o più else if
    //il codice qui non viene eseguito perchè "miao" non comincia per "c"
}
else {
    //il codice qui viene eseguito se tutte le condizioni prcedenti sono false
}

if (z) console.log("la variabile z è truthy"); //se si mette una sola variabile questa viene trasformata in booleano

if (cane != gatto) { //condizione vera
    if (cane == z) { //condizione falsa
        //
    }
    else {
        if (gatto == "miao") { //condizione vera
            console.log("il gatto fa miao");
        }
    }
}

if (!z) {
    var pig = "oink";
    let fish = "..."; 
}
console.log(pig); //"oink"
console.log(fish); // Uncaught ReferenceError: fish is not defined

switch case

Il costrutto switch(variabile) {case "opzione": {istruzioni} break;} serve per eseguire un codice diverso a seconda del valore della variabile indicata nelle parentesi tonde. I diversi valori che può assumere la variabile sono indicati dalla parola chiave case ed il relativo codice è contenuto nelle parentesi graffe dopo i due punti.

Il valore della variabile viene confrontato con ogni case in successione. Appena viene trovata la prima corrispondenza verrà eseguito il codice relativo ed anche tutti quelli successivi. Per fare in modo che venga eseguito solo il codice relativo al case corrispondente dobbiamo inserire la parola chiave break che permette di uscire dal costrutto switch case.

Se nessuno dei valori dei vari case corrisponde al valore della variabile allora viene eseguito il codice indicato dal case default.

Spesso si usa lo switch case in alternativa al costrutto if...else. Conviene usare switch case quando si conoscono i valori che la variabile potrebbe assumere, altrimenti è meglio usare if (per esempio in caso di condizioni del tipo "se a è maggiore di b" ma non sappiamo il valore di a e b usiamo l'if).

var segno = "toro";
switch (segno) {
    case "ariete":
        console.log("Oggi sarai molto fortunato, gioca alla lotteria!");
        break; //Attenzione! ricordarsi sempre il break
    case "toro":
        console.log("Oggi ti andrà tutto male, non uscire di casa!");
        break;
    case "gemelli":
    case "cancro": //verrà eseguito lo stesso codice in entrambi i casi
        console.log("Oggi sarà una giornata normale, fai un po' quello che vuoi.");
        break;
    default: //se nessuno dei casi precedenti risulta vero viene eseguito il case di default
        console.log("Il tuo oroscopo non è pervenuto."); 
}

//il codice precedente può anche essere scritto come:
if (segno == "ariete") {
    console.log("Oggi sarai molto fortunato, gioca alla lotteria!");
}
else if (segno == "toro") {
    console.log("Oggi ti andrà tutto male, non uscire di casa!");
}
else if (segno == "gemelli" || segno == "cancro") {
    console.log("Oggi sarà una giornata normale, fai un po' quello che vuoi.");
}
else {
    console.log("Il tuo oroscopo non è pervenuto.");
}

while / do while

Il costrutto while(condizione) {istruzioni} serve per eseguire ciclicamente il codice indicato nelle parentesi graffe finchè la condizione contenuta nelle parentesi tonde risulta vera. Ad ogni iterazione viene verificata la condizione e se questa è ancora vera il codice viene eseguito, altrimenti il ciclo si ferma. Se la condizione risulta falsa in partenza il ciclo non parte.

Nell'esempio vengono calcolati i primi 20 numeri della successione di Fibonacci.

var a = 0;
var b = 1;
var temp;
var counter = 1;

while (counter <= 20) {
    console.log(a);
    temp = a + b;
    a = b;
    b = temp;
    counter++;
}

Se invece vogliamo che il codice sia prima eseguito e poi sia verificata la condizione dobbiamo usare il costrutto do {istruzioni} while(condizione); . Nell'esempio vediamo che l'ultimo numero generato è inferiore a 1 anche se la condizione è che la variabile mezzo sia maggiore di 1 proprio perchè prima viene eseguito il codice e dopo viene fatta la verifica.

var intero = 500;
do {
    var mezzo = intero / 2;
    console.log(mezzo);
    intero = mezzo;
}
while (mezzo > 1);

for

Il costrutto for(inizializzazione; condizione; incremento) {istruzioni} serve per eseguire ciclicamente il codice contenuto nelle parentesi graffe finchè la condizione indicata come secondo parametro nelle parentesi tonde risulta vera. Il primo parametro viene valutato solo una volta all'inizio del ciclo e rappresenta l'inizializzazione del contatore. Ad ogni iterazione viene verificata la condizione e se questa è ancora vera il codice viene eseguito e il contatore (terzo parametro) aumenta di una unità.

Nell'esempio vengono calcolati i primi 10 numeri della successione di Fibonacci.

I costrutti for possono anche essere annidati uno dentro l'altro. Nell'esempio viene generata la tavola pitagorica.

var a = 0;
var b = 1;
var temp;
for (var i = 1; i < 10; i++) {
    console.log(a);
    temp = a + b;
    a = b;
    b = temp;
}

var i = 1; //la variabile di inizializzazione si può anche definire fuori
for (; i < 10; i++) { //Attenzione al ;
    // ...
}

for (var i = 1; ; i++) { //si può omettere la condizione qui e spostarla all'interno
    //...
    if (i > 10) break; //bisogna per forza mettere un break per interrompere il ciclo
}

for (var i = 1; i > 10;) { //si può omettere anche l'incremento
    //...
    if (i > 10) break;
    i++; //mettere qui l'incremento della variabile che viene controllata
}

var a = 0;
var b = 1;
var temp;
for (var i = 1, z = 5, text = "ciao"; i < 100; i++) { //si possono definire più variabili di inizializzazione
    if (a % z == 0) {
        console.log(text + " " + a);
    }
    temp = a + b;
    a = b;
    b = temp;
}

//for loop per scorrere un array
var arr = [1, 2, 3];
for (var i = 0; i <= arr.length; i++) {
    console.log(arr[i]); //1, 2, 3
}
var l = arr.length; //la lunghezza del'array si può anche mettere fuori in modo che non debba essere ricalcolata ogni volta
for (var i = 0; i <= l; i++) {
    console.log(arr[i]); //1, 2, 3
}

//il ciclo for si può fare anche all'indietro
for (var i = arr.length - 1; i >= 0; i--) {
    console.log(arr[i]); //3, 2, 1
}

//due cicli for annidati
for (var i = 1; i <= 10; i++) {
    for (var j = 1; j <= 10; j++) {
        console.log(i + " x " + j + " = " + (i * j));
    }
}

//differenza tra usare var e let per l'inizializzazione
for (var i = 0; i < 3; i++) {
    console.log(i); //0, 1, 2
}
console.log(i); // 3

for (let w = 0; w < 3; w++) {
    console.log(w); //0, 1, 2
}
console.log(w); // Uncaught ReferenceError: w is not defined

for of

Il costrutto for of serve per iterare su un iterable come ad esempio un array, un Map o un Set.

var frutta = ["ananas", "banana", "cocco", "dattero"];
for (let f of frutta) {
    console.log(f); //"ananas", "banana", "cocco", "dattero"
}

var str = "casa";
for (let s of str) {
    console.log(s); // "c", "a", "s", "a"
}

var map = new Map();
map.set("lat", 45.789);
map.set("long", 7.897);
for (let m of map) {
    console.log(m); // ["lat", 45.789], ["long", 7.897]
}

var arr = [7, 12, 23, 55];
var values= arr.values();
for (let k of values) {
    console.log(k); // 7, 12, 23, 55
}

//come usare for of con gli oggetti
var persona = {
    nome: "Mario",
    cognome: "Rossi",
    anni: 20
}
for (let [key, value] of Object.entries(persona)) {
    console.log(`${key}: ${value}`); // "nome: Mario" "cognome: Rossi" "anni: 20"
  }

for in

Il costrutto for in serve per iterare su tutte le enumerable properties di un oggetto incluse quelle ereditate. 

var persona = {
    nome: "Mario",
    cognome: "Rossi",
    anni: 20
}

for (let p in persona) {
    console.log(p); //"nome", "cognome", "anni"
}

class Cat {
    constructor(color) {
        this.color = color;
    }
    greet() {
        return "meow!"
    }
}

class Lion extends Cat {
    constructor(color, speed) {
        super(color);
        this.speed = speed;
    }
}

var simba = new Lion("marrone", 100);

for (let p in simba) {
    console.log(p); //"color", "speed" non c'è "greet"
}

//non usare il for in con gli array perchè non è garantito l'ordine
var arr = ["Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato", "Domenica"];

for (let p in arr) {
    console.log(p); //"0", "1", "2", "3", "4", "5", "6"
}