Supponiamo di avere una serie di elementi ( nell'esempio qui riportato dei div ) e voler loggare un valore quando passiamo sopra ad ognuno.
In prima battuta scriveremmo un codice del tipo:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Test</title>
<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.4/dojo/dojo.xd.js"></script>
<script>
dojo.addOnLoad(function( ) {
for (var i=1; i < 6; i++) {
var foo = dojo.byId("div"+i);
var handle = dojo.connect(foo, "onmouseover", function(evt) {
console.log(i);
dojo.disconnect(handle);
});
}
})
</script>
</head>
<body>
<div id="div1" style ="background-color:#EEEE00;">Div1</div>
<div id="div2" style ="background-color:#FF0000;">Div2</div>
<div id="div3" style ="background-color:#4466FF;">Div3</div>
<div id="div4" style ="background-color:#F2921F;">Div4</div>
<div id="div5" style ="background-color:#444444;">Div5</div>
</body>
</html>
Il risultato però non è quello voluto. Innanzitutto viene sempre loggato il valore 6 mentre, ad eccezione del div5, il disconnect non viene rispettato.
Se ci pensiamo su un attimo, questo ha senso perchè la closure fornita dalla funzione anonima passata al dojo.connect non risolve la variabile i finchè non viene eseguita.
Per risolvere il problema intrappoliamo lo scope della variabile all'interno della funzione cosicchè, quando più tardi faremo riferimento, verrà risolto il valore precedentemente trattenuto.
In sostanza occorre inserire il corpo del loop in una funzione anonima che viene eseguita inline. Poichè la funzione anonima fornisce una closure di tutto quello che è contenuto, possiamo intrappolare con una variabile (current) il valore i. Inoltre risolviamo pure il problema dell'handle perchè anche per questo c'è la closure della funzione anonima.
for (var i=1; i < 6; i++) {
(function(){
var current= i;
var foo = dojo.byId("div"+i);
var handle = dojo.connect(foo, "onmouseover", function(evt) {
console.log(current);
dojo.disconnect(handle);
});
})();
}