View Full Version : javascript e lo scope.. problemini..
Ciao,
ho un dubbio che non capisco :/
faccio un esempio almeno rendo il tutto di più semplice comprensione :
cosi il tutto funziona correttamente :
var bottoni = document.getElementsByTagName('BUTTON');
for(var i=0; i<menu.length; i++)
{
bottoni[i].onclick = (function(){ // Definisci la funzione in cui ti salvi il valore corrente della i
var currentI = i;
return function(){ // ritorni la funzione (currentI sarà sempre diversa ad ogni iterazione perché cambia lo scope)
recinto.setLevel(currentI);
recinto.inizializzazione();
}
})();
}
mentre se faccio :
for(var i=0; i<3; i++)
{
bottoni[i].onclick = function(){
recinto.setLevel(i);
recinto.inizializzazione();
}
ogni bottone prende setLevel con i=3 .. non capisco.. il passaggio non dovrebbe essere per valore ? come mai qui lo fa come riferimento ???
DanieleC88
09-07-2013, 01:21
Stai creando una funzione in un loop, che in JavaScript è una cosa generalmente sconsigliata esattamente per il "problema" che stai affrontando.
Ciò che accade, in realtà, è che nel loop stai facendo soltanto un'assegnazione, cioè una cosa del tutto simile alla seguente:
for (var i = 0; i < collection.length; ++i) {
object.property = value;
}
Contestualizzando l'esempio al tuo codice, si dà il caso che questo valore sia una funzione (che verrà invocata al click di un pulsante), e questa si accompagna ad una cattura delle variabili dello scope esterno che sono utilizzate al suo interno. In sostanza: stai catturando non il valore dell'indice i al momento dell'iterazione, ma un riferimento ad esso. Al momento del click (e, quindi, dell'invocazione dell'handler), tale indice ha il valore che lo ha fatto uscire dal loop: ecco perché vedi i = 3.
Il tuo primo snippet è corretto. In realtà, però potresti anche evitarti la nuova variabile currentI, visto che stai usando una IIFE (http://en.wikipedia.org/wiki/Immediately-invoked_function_expression), alla quale puoi passare direttamente il valore di i:
var bottoni = document.getElementsByTagName('button');
for (var i=0; i < menu.length; ++i) {
bottoni[i].onclick = (function (i) {
return function() {
recinto.setLevel(i);
recinto.inizializzazione();
};
})(i);
}
In questo modo hai che:
il nome del parametro dell'IIFE sta nascondendo l'omonimo indice del loop esterno, quindi puoi utilizzare senza paura lo stesso nome anche nella funzione più interna;
il valore associato a tale parametro è quello assunto durante la corrispondente iterazione.
HTH
__ZERO_UNO__
09-07-2013, 13:47
Long story short, for non ha scope come le funzioni. Quando la funzione è invocata, i viene cercata e trovata nello scope esterno ed avrà l'ultimo valore che gli è stato assegnato.
Non ragionare in termini di passaggio per valore o riferimento–che non parlando di argomenti di funzione non ha alcun senso–, bensì in termini di scope.
Long story short, for non ha scope come le funzioni. Quando la funzione è invocata, i viene cercata e trovata nello scope esterno ed avrà l'ultimo valore che gli è stato assegnato.
Non ragionare in termini di passaggio per valore o riferimento–che non parlando di argomenti di funzione non ha alcun senso–, bensì in termini di scope.
giusto :) Ora comunque mi è tutto molto più chiaro :) Grazie ragazzi ! ancora una volta mi avete spiegato qualcosa con un linguaggio semplicissimo :) :cincin:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.