| Summary: Questo tutorial spiega i meccanismi di base sulla visibilità delle variabili e sugli ambiti (scope) in javascript. |
| Author: Jozef Sakalos (traduttore: Giacomo Magisano) |
| Published: August 23, 2007 |
| Ext Version: 1.1+ / 2.0+ |
Languages: English Chinese Korean French Turkish Italian
|
Contents |
Prima di iniziareIl modo migliore per studiare questo tutorial è avere a disposizione Firefox e Firebug. In questo modo sarà possibile provare gli esempi presenti nel tutorial immediatamente.
Installate entrambi se non l'avete già fatto.
Definizioneambito (scope)
1. (s.m.) Spazio circoscritto entro cui ci si muove e si agisce; margine concesso all'azione SIN cerchia, giro [1]
2. (s.m) In programmazione, la visibilità di una variabile all'interno di un programma; per esempio, se una funzione possa utilizzare una variabile dichiarata in un'altra funzione.[2]
Con cosa avremo a che fare? Stiamo per scoprire se e quando una variabile sarà utilizzabile durante l'esecuzione di una funzione e cosa intende quanlcuno quando ci apostrofa con "è un problema di scope", "sta eseguendo nello scope sbagliato" o affermazioni simili.
PartiamoOgni funzione che possiamo definire in Javascript è un metodo di un oggetto. Anche scrivendo qualcosa di simile:
function fn() { alert(11); }
Potreste pensare che sto scherzando. Potete verificare molto semplicemente la mia affermazione. Non c'è neanche bisogno di scrivere un file Javascript, di avere a disposizione un server o una pagina html. Aprite semplicemente Firefox, quindi Furebug e selezionate la console. Appena sopra la barra di stato di Firefox potrete vedere una linea che comincia con >>> dove è possibile digitare codice. In caso non ci sia il prompt >>> in fondo alla finestra disattivate dal menù Options la voce Larger Command Line.
Digitate
function fn() { alert(11); };
e premete Invio. Sembra che non sia successo niente' In realtà avete appena definito la funzione fn.and Enter. ora provate a digitare
fn();
e premere Invio. E' partita una message box con 11? Bene. Ora provate
window.fn(); this.fn();
E' successa la stessa cosa?
Questo si verifica perché la funzione fn è, in realtà, un metodo dell'oggetto window. La seconda istruzione ci da la prova che la variabile this equivale all'oggetto window [NDT: con Firebug 1.2.0b7 (e superiori?) this punta a Firebug e quindi quest'ultimo assunto non è più valido. resta valido se il test viene eseguito dall'interno di una pagina html di prova]
La possibilità di invocare le proprie funzioni senza utilizzare la notazione window.myFunction(...) è solo zucchero sintattico per rendere più facile e conveniente il lavoro dei programmatori svogliati.
L'oggetto windowL'oggetto window è sempre presente -- potete immaginarlo come se fosse la finestra del browser. Contiene tutti gli altri oggetti come, ad esempio, l'oggetto document e tutte le variabili globali.
Potete aprire Firebug, andare alla sezione Script e digitare window nella casella "New watch expression..." sul lato destro di Firebug, e premete Enter. Potete, a questo punto, esplorare l'oggetto window per capire cosa contiene. In alternativa basta andare nella sezione DOM ed avere le stesse informazioni riquardo l'oggetto windowp.
In particolare, cercate la funzione fn che abbiamo definito prima.
Ogni frame o iframe ha il proprio oggetto window ed il proprio spazio globale.
Capire gli Ambiti (scope)Complichiamo un attimo le cose. Torniamo alla console di Firebug e scriviamo
var o1 = {testvar:22, fun:function() { alert('o1: ' + this.testvar); }}; var o2 = {testvar:33, fun:function() { alert('o2: ' + this.testvar); }};
Cosa abbiamo fatto? Abbiamo definito gli oggetti o1 e o2 ognuno con le stesse proprietà e gli stessi metodi. Le proprietà, pero, contengono valori differenti.
Ora proviamo:
fun(); window.fun(); this.fun();
Sono stati segnalati degli errori, non è vero? E' normale: l'oggetto window (che equivale a this) non ha un metodo fun. Proviamo, invece, queste altre istruzioni:
o1.fun(); o2.fun();
Dovremmo aver ottenuto 22 e 33.
Ed ora aggiungiamo l'ultima complicazione. Abbiamo funzioni primitive che non vorremmo replicare per ognuno dei nostri oggetti. Ipotizziamo che o1.fun sia una funzione molto complessa e ingegnosa che abbiamo messo a punto lavorandoci per tutta la scorsa settimana. Immaginiamo che siano più di 100 linee di codice inframezzate da molteplici riferimenti a this. Come possiamo invocare (eseguire) o1.fun facendo in modo che punti all'oggetto o2? Provate con questa chiamata:
o1.fun.call(o2);
Abbiamo forzato la variabile this a puntare all'oggetto o2 mentre stavamo eseguendo il metodo fun di o1, in altre parole, usando una terminologia più formale, il metodo o1.fun sta eseguendo nell'ambito dello scope dell'oggetto o2.
Possiamo pensare allo scope come al valore della variabile this mentre viene eseguita una funzione, un metodo di un oggetto.
Visibilità delle variabiliLa visibilità delle variabili è strettamente legata al concetto di ambito (scope). Sappiamo già che le variabili (anche le funzioni sono variabili) definite al di fuori da ogni oggetto o funzione sono globali o, tecnicamente, sono proprietà dell'oggetto globale window.
Le variabili globali sono visibili dovunque; all'interno ed all'esterno di tutte le funzioni. Se si modifica il valore di una variabile globale all'interno di una funzione, le altre funzioni vedranno il valore modificato.
Sappiamo anche che gli oggetti hanno proprietà proprie (come testvar qui sopra) che sono visibili sia all'interno che all'esterno dell'oggetto. Proviamo:
alert(o1.testvar); // accesso alla proprietà testvar di o1 dall'esterno
L'accesso dall'interno dell'oggetto è già stato dimostrato nei metodi fun di entrambi gli oggetti di test.
L'ultimo pezzo del puzzle sono le variabili locali definite all'interno di funzioni con la parola chiave var:
i = 44; function fn2() { var i = 55; alert(i); } fn2();
Che cosa si ottiene? 55. La variabile i definita in fn2 è locale alla funzione fn2 e non ha nulla a che fare con la variabile globale i che equivale a 44.
Ma:
alert(i);
restituirà 44 visto che fa riferimento all variabile globale i.
Spero che questo tutorial abbia gettato un po di luce sugli ambiti e sulla visibilità delle variabili.
Approfondimenti: