edutecnica

Strutture di controllo in JavaScript

      

L'importanza delle strutture di controllo nei linguaggi di programmazione risiede nel fatto che attraverso di esse l'elaboratore viene messo in condizione di prendere delle decisioni autonome.

I costrutti fondamentali del linguaggio Javascript rimangono quelli già visti in C e Java, in particolare abbiamo la selezione binaria data dall'istruzione if-else:

if(condizione){
     //istruzioni-a
}else{
     //istruzioni-b
}

dove viene usato il marcatore // per il commento di una singola linea;
mentre per i commenti multilinea si usano i marcatori /* . . . */
Ricordiamo che nel caso venga eseguita una singola istruzione sul ramo if e/o sul ramo else, le parentesi graffe non sono obbligatorie.
La stessa clausola else non è obbligatoria; cioè si può anche fare



if(condizione){
     /* istruzioni-a */
}

La differenza è evidente, nel primo caso l'elaboratore esegue comunque 'qualcosa' nel secondo caso non è detto che faccia 'qualcosa' :se la condizione logica di test è falsa può anche non fare niente (e passare alle istruzioni successive).

Un esempio di if semplice (privo di else) è il seguente scritto che ottiene la radice quadrata della variabile x solo ed esclusivamente se essa contiene un valore numerico maggiore o uguale a zero.


Come si vede, per l'estrazione di radice, si fa uso dell'oggetto Math e della funzione sqrt() già vista in linguaggio Java; si può affermare che le varie funzioni matematiche hanno lo stesso identificatore (nome) in entrambi i linguaggi.

Una variante dell'esempio precedente che prevede l'uso della sintassi completa if-else ,è la seguente, dove nel caso il valore numerico della variabile x sia negativo viene mandato in output un segnale di errore.


Il costrutto if nella sua forma completa può essere sostituito da una forma più sintetica costituita dall'operatore ternario caratterizzato dalla seguente sintassi:

(condizione) ? se_vero : se_falso;      come è possibile notare nel seguente listato:


Un costrutto comune in tutta la programmazione dei calcolatori è l' if-else-if : una struttura a scala che ha la seguente forma




if (condizione_1)     {istruzioni_a;}
else if (condizione_2){istruzioni_b;}
else if (condizione_3){istruzioni_c;}
. . .
else {istruzioni_n;}

Il calcolatore inizia la valutazione delle espressioni condizionali dall'alto verso il basso ed esegue la prima che viene verificata (true) abbandonando, dopo aver eseguito il blocco di codice corrispondente, la catena di if.
Se non si verifica nessuna delle condizioni, viene eseguito l' else finale, che spesso ha il significato concettuale di condizione di default.
Se non è presente l'ultimo else, qualora non si sia verificata nessuna delle condizioni, non viene intrapresa nessuna azione.
Nell'esempio che segue viene fatto uso di una struttura if-else-if per determinare se abbiamo indovinato un numero casuale da 0 a 9 che il computer ha 'pensato'.


Sebbene il costrutto if-else-if consenta di realizzare dei test multipli, è da considerare una struttura poco elegante che può risultare di difficile lettura.
Per queste ragioni, quando il test multiplo viene eseguito su dei valori costanti è conveniente usare la struttura switch.
In questo costrutto il valore di una variabile viene confrontato con una lista di costanti; quando si verifica una uguaglianza, si esegue il blocco di istruzioni corrispondenti:

switch(variabile){
     case costante_1 : istruzioni_a; break;
     case costante_2 : istruzioni_b; break;
     case costante_3 : istruzioni_c; break;
     . . .
     default: istruzioni_n;
}

in questa sintassi, la parte default è opzionale, e se è presente viene eseguita nel caso in cui non si verifichi alcuna corrispondenza.
Se non è presente la clausola default e non ci sono corrispondenze, non viene eseguita nessuna azione.
Quando viene trovata una corrispondenza, sono eseguite le istruzioni associate al case fino all'istruzione break.
Nonostante l'eleganza formale, i test del costrutto switch possono solo verificare l'uguaglianza a differenza di quelli dell' if-else-if che possono verificare condizioni di qualsiasi tipo.
Con tutta probabilità l'istruzione switch() è stata introdotta per soddisfare alcuni bisogni primari dell'uomo, quali l'accesso alle funzioni di un bancomat:


Le istruzioni break non sono indispensabili all'interno di uno switch, in quanto nel caso siano assenti l'esecuzione del programma prosegue nelle istruzioni relative al case successivo, fino a quando non viene incontrato il primo break o la fine della struttura di controllo.
I case possono essere considerati come delle etichette che indicano i punti di entrata nel codice, mentre i punti di uscita sono i break e la fine del costrutto.


Cicli iterativi

            

I cicli indicano al calcolatore di eseguire un insieme di istruzioni fino a quando non è verificata una determinata situazione. I tipi di ciclo permessi in JS sono gli stessi presenti negli altri linguaggi di programmazione; si tratta del ciclo while, del ciclo do-while e del ciclo for.

La struttura di controllo ciclica consente di tornare ad un punto precedente del programma e ripetere un blocco di istruzioni per lo stato attuale, il tipo di ciclo più semplice da scrivere è il ciclo while:





while(condizione){
     /* istruzioni */
}

Nel seguente esempio, la variabile n viene inizializzata a 0, poi entra in un ciclo while dove viene stampata a video e viene successivamente incrementata di 1 (n++) il ciclo continua finchè è vera (true) la condizione logica espressa tra le parentesi dell'istruzione while.


Il ciclo, viene dunque ripetuto, fin tanto che rimane vera la condizione specificata.
Quando la condizione diventa falsa, l'esecuzione procede dalla prima istruzione successiva al ciclo (nel nostro caso il programma termina).
Il fatto che la condizione logica sia verificata all'inizio del loop, comporta l'eventualità che il ciclo possa anche non essere eseguito nemmeno una volta.

A differenza del ciclo while che verifica la condizione all'inizio del loop, il ciclo do-while esegue la verifica alla fine, con la conseguenza che il do-while viene eseguito almeno una volta




do{
     /* istruzioni */
}while(condizione);

In questo caso usiamo il costrutto do-while per acquisire 5 numeri da tastiera per restituirne la somma. Abbiamo bisogno di una variabile contatore i inizializzata a 0 come la variabile sum che sarà usata come accumulatore.


Per l'acquisizione da tastiera viene usata la funzione standard prompt() che serve per impostare una domanda aperta e consente di usare una finestra di dialogo per l'inserimento del valore.
Per definizione tutti i linguaggi di programmazione, da tastiera, acquisiscono esclusivamente stringhe; ecco il motivo del perchè l'istruzione prompt() viene incapsulata come argomento nella funzione parseInt(); che ha il solo scopo di convertire (se possibile) l'input acquisito dalla funzione prompt() in un numero intero.
La funzione isNaN() è una funzione standard JS che restituisce true solo se l'argomento passato è NaN (Not a Number=non un numero) in questo caso la sua forma negata !isNaN(n) sarà true solo se n rappresenta effettivamente un numero.
La variabile contatore i, parte da 0 e compie 5 iterazioni (da 0 a 4 inclusi). Ad ogni iterazione la variabile sum viene incrementata del valore del numero n inserito da tastiera.

In ogni caso, il seguente esempio, mette in evidenza la differenza fondamentale tra i due costrutti while e do-while


All'interno della pagina inseriamo due tag, il primo con identificatore id="W" per il ciclo while, il secondo con indentificatore id="DW" per il do-while; nello scritto che segue, la variabile n viene posta a 15 ma l'immediato controllo del while(n<10)n++; impedisce ad n di incrementarsi perchè la condizione logica è da subito falsa, quindi nel tag del while il valore di n viene stampato a 15.
Poi per sicurezza reimpostiamo il valore di n a 15 e tentiamo di incrementare n attraverso il costrutto do{n++;}while(n<10); prima di essere espulsa dal ciclo la n viene incrementata di 1; questo perchè il test di validità, in questo caso viene eseguito alla fine dello stesso.

Sia il costrutto while che il do-while vengono usati quando a priori non sappiamo quante iterazioni si devono fare, ma quando questo numero è noto, si può usare il ciclo for che in tutti linguaggi di programmazione procedurale appare con la sintassi:





for(inizalizzazione;condizione;incremento){
   /* istruzioni */
}

L'inizializzazione è, nella sua forma più semplice, un istruzione di assegnamento con la quale si posiziona il valore iniziale della variabile di controllo del ciclo.
La condizione è una espressione relazionale usata per valutare la variabile di controllo al fine di determinare il momento di uscita dal ciclo; l'esecuzione procede fintanto che la condizione è vera, mentre quando diviene falsa l'esecuzione precede con le istruzioni successive al for.
L'incremento definisce il modo in cui la variabile di controllo cambia il suo valore ad ogni ripetizione di ciclo.
Queste tre parti devono essere separate da un punto e virgola.


In questo caso il for eseguirà 8 iterazioni (dettate dalla costante n) da con la variabile di controllo i che varia da 0 a 7 inclusi, ad ogni esecuzione la stessa variabile viene stampata in output perchè questo è scritto nel corpo del ciclo.

E' possibile predisporre dei costrutti for che prevedano l'uscita prematura dal ciclo.
Nel seguente esempio usiamo un for per acquisire una sequenza di 5 numeri interi di cui poi vogliamo calcolare la somma.


All'interno del corpo del for è stato inserito un if che valuta se il valore inserito da tastiera può essere assimilato ad un numero.
Se si cerca di inserire una stringa qualsiasi, il ciclo si interrompe stampando il valore della somma fin lì calcolata.


Tag di selezione

            

Oltre ai tag di input per la casella di testo, indicata attraverso la forma

<input type="text" >

ed al pulsante di azione

<input type="button" >

è possibile realizzare in HTML altri tipi di elementi, in particolar modo oggetti riservati alla selezione, quali la casella combinata a discesa definita dai tag select/option nel seguente modo:

<select id="sel">
<option value="A" >Opzione 1
<option value="B" >Opzione 2
<option selected value="C">Opzione 3
</select>

In JavaScript è poi possibile determinare quale elemento sia stato selezionato


Notiamo come sia possibile usare lo specificatore selected per definire quale item può essere selezionato in via preliminare; è inoltre possibile, accedere all'attributo di un singolo item, leggendo il suo valore, attraverso la proprietà .value, oppure è possibile accedere all'indice dell'item selezionato, attraverso l'attributo .selectedIndex, mentre la voce riportata esplicitamente in elenco può essere acquisita leggendo la proprietà .options[indice].text, che può essere usata a patto di conoscere l'indice dell'elemento selezionato.
A tal proposito, si deve notare che il primo item dell'elenco ha sempre indice 0 (zero) come nel caso dei vettori (array) già visti negli altri linguaggi di programmazione.

Un altro strumento di selezione che può essere usato è la casella di spunta (checkbox). La checkbox è dotata dell'attributo .checked che contiene un valore booleano (true/false) in grado di rivelare se la casella in questione è stata selezionata oppure no.
Il seguente esempio fa uso di questa proprietà ed è stato organizzato in modo di gestire due caselle di testo per mutua esclusione.


Stavolta un gestore di eventi onclick è stato associato a ciascuna casella, in modo da chiamare due funzioni che resettano la casella opposta a quella appena selezionata. In assenza di queste funzioni sarebbe possibile selezionare anche più checkbox simultaneamente.
In alternativa alle checkbox, sarebbe possibile utilizzare i pulsanti radio; ma per fare questo è sufficiente sostituire il tipo specificato; cioè scrivere

<input type="radio". . .       al posto di        <input type="checkbox" . . .

Ma questo è solo un fatto estetico.