Il logo di batmath
www.batmath.it

Osservazioni sull'ordine di esecuzione delle istruzioni Javascript

In questa pagina intendiamo fornire solo alcune indicazioni di massima relativamente al problema dell'ordine in cui le istruzioni vengono eseguite in Javascript. L'idea di base è che l'esecuzione degli script si verifica come parte del processo di analisi del codice HTML da parte del browser (operazione che viene chiamata parsing, cioè analisi sintattica). Poiché il parsing avviene sequenzialmente, anche il codice javascript viene eseguito nell'ordine in cui compare nella pagina HTML: in sostanza il parser HTML passa il codice all'interprete javascript, che è incorporato nel browser stesso, man mano che procede nell'interpretazione della pagina. 

Questo fatto riveste un'enorme importanza per quanto riguarda, per esempio, la dichiarazione e l'uso delle variabili: se nel BODY della pagina è presente un form dal nome "ciccio", con una casella di testo dal nome "patata", un codice javascript inserito nell'HEAD del documento non potrà far riferimento a questi oggetti come variabili globali. E', invece, perfettamente lecito definire una funzione che opera su oggetti che non sono ancora stati creati, perché nello script la funzione viene solo definita, non eseguita: solo nel momento in cui la funzione viene richiamata, per esempio da un evento onclick, è indispensabile accertarsi che tutti gli oggetti che essa usa siano stati definiti. 

Altra conseguenza di questo fatto è che se, per esempio, ho bisogno di definire una variabile globale e questa variabile deve venire reinizializzata da una certa funzione ogni volta che la funzione viene chiamata, la inizializzazione deve avvenire all'interno della funzione e non fuori. Nel codice relativo alla scomposizione in fattori di un naturale abbiamo dichiarato una variabile globale k, che però deve venire reinizializzata ogni volta che la funzione scomponi viene chiamata: per questo all'interno della funzione scomponi abbiamo posto l'istruzione k=0.

Ulteriore importante punto da tenere presente è il seguente: se un codice deve eseguire un'operazione che richiede molto tempo, è bene che il codice non venga eseguito fin quando l'utente non lo richiede esplicitamente. Nel primo esempio del programma sul calcolo dei fattoriali l'esecuzione del codice avviene automaticamente, senza intervento da parte dell'utente: se il tempo di esecuzione fosse troppo lungo l'utente potrebbe pensare che il programma sia rimasto in sospeso, si sia bloccato o che il browser sia andato in crash. 

 A proposito di questo esempio osserviamo che se modifichiamo il codice javascript in modo da inserire le istruzioni all'interno dello script senza l'intervento di una funzione, non sarà più necessario l'uso di alcun gestore di eventi: il codice viene interpretato riga per riga all'atto del caricamento della pagina e direttamente eseguito.

Riportiamo per chiarezza l'intero codice della pagina originale e di quella modificata.

Pagina originale

<html>
<head>
<title>Calcolo del fattoriale dei numeri da uno a dieci</title>
<script language="JavaScript">
function fattoriale() {
   document.write("<h3>I fattoriali dei numeri da 1 a 10</h3>");
   for(i=1,fatt=1;i<11;i=i+1,fatt=fatt*i)
  {
document.write(i + "! = "+ fatt);
document.write("<br>");
  }
}
</script>
</head>
<body onload="fattoriale()">
</body>
</html>

Pagina modificata

<html>
<head>
<title>Calcolo del fattoriale dei numeri da uno a dieci</title>
<script language="JavaScript">
 document.write("<h3>I fattoriali dei numeri da 1 a 10</h3>");
 for(i=1,fatt=1;i<11;i=i+1,fatt=fatt*i)
  {
document.write(i + "! = "+ fatt);
document.write("<br>");
  }
</script>
</head>
<body>
</body>
</html>

C'é anche un'altra importante differenza in esecuzione tra i due codici: nel primo caso il codice della funzione fattoriale viene eseguito dopo il caricamento della pagina per cui il metodo document.write provoca l'apertura di un nuovo documento e la scrittura dell'output in questo nuovo documento; nel secondo caso il codice viene letto ed eseguito mentre il documento è ancora in caricamento e quindi l'output avviene nella stessa pagina. Per rendersi conto di questo fatto si provi a scrivere (o a copiare con la funzione copy and paste) i due codici e ad eseguirli, controllando poi con il pulsante back la history del browser.

Per rendere più chiaro il problema presentiamo due pagine HTML con una parte di codice javascript: la prima provoca un messaggio di errore, la seconda no. Il tipo di messaggio di errore dipende dal browser in uso e dalle impostazioni personali del browser, e potrebbe limitarsi ad un semplice messaggio nella barra di stato in fondo alla pagina. In ogni caso si ricordi che se viene incontrato un errore javascript la pagina viene comunque caricata e il codice HTML eseguito (eventualmente dopo la comparsa di un messaggio di errore in cui si richiede di cliccare su un bottone).

Pagina HTML con un errore

<html>
<head>
<script>
document.ciccio.patata.value="Bravo, 7+!!";
</script>
</head>
<body>
<form name="ciccio">
<input type="text" name="patata">
</form>
</body>
</html>

Al momento del parsing del codice HTML della pagina, quando si incontra lo script il form con la sua casella di testo non è ancora stato definito e quindi l'interprete javascript non lo conosce. Dopo l'eventuale comparsa del messaggio di errore il resto del codice HTML viene normalmente eseguito, ma nella casella di testo non compare nulla.

Una possibile variante corretta della pagina

<html>
<head>
</head>
<body>
<form name="ciccio">
<input type="text" name="patata">
</form>
<script>
document.ciccio.patata.value="Bravo, 7+!!";
</script>
</body>
</html>

In questa variante, invece, al momento del parsing del codice HTML della pagina, quando si incontra lo script il form con la sua casella di testo è già stato definito e quindi l'interprete javascript lo conosce. Viene quindi correttamente visualizzata la casella di testo con la scritta prevista.

Un'altra possibile variante corretta si ottiene con l'introduzione di una function, la cui attivazione deve però essere gestita da un evento: come esempio abbiamo proposto l'evento onload, nel tag BODY, perché non richiede interventi da parte dell'utente.

<html>
<head>
<script>
function prova() {
document.ciccio.patata.value="Bravo, 7+!!"; }
</script>
</head>
<body onload="prova()">
<form name="ciccio">
<input type="text" name="patata">
</form>
</body>
</html>

In questo caso al momento del parsing del codice HTML la funzione viene solo definita, non eseguita. E' solo quando la funzione viene chiamata, cioè al termine del caricamento della pagina (questo fa l'evento onload) che l'interprete javascript controlla se tutti gli oggetti utilizzati sono stati definiti o no. Per questo il codice funziona regolarmente. Questo script poteva anche essere piazzato nel BODY del documento, anziché nell'HEAD, sia prima che dopo l'introduzione del form, senza alcuna differenza nel risultato.

pagina pubblicata il 01/11/2001 - ultimo aggiornamento il 01/09/2003