Pokusím se to vysvětlit jednoduše.
Nejdřív kde je problém v původním kódu:
updates[counter] = window.setInterval('update(1, counter)', 10000);
Zde předáváš do setInerval řetězec s JS kódem. To znamená, že ve chvíli spuštění události (cca každých 10000ms) se vlastně provedel eval (což je mimochodem důvod, proč je předávání řetězců do setInerva a setTimeout považováno za nedobré). Ve chvíli vyhodnocení kódu je potřeba proměnná counter, ta je nalezena v globálním oboru platnosti. V tu chvíli je v ní ale již hodnota 2.
Řešení využívá lexikálního uzávěru (neboli closure). Princip: v každé funkci máš přístup k lokálním proměnným deklarovaným pomocí klíčového slova var (viz http://zapisnik.pepiino.cz/co-byste-meli-vedet-o-javascriptu-1-promenna-a-globalni-obor-platnosti/), jejím parametrům (a pak this, arguments ..., to nás ale teď nezajímá) a navíc k lokálně dostupným proměnným funkce, v jejížm těle byla deklarována. Tento princip se řetězí (tedy "lokálně dostupné proměnné funkce v níž byla deklarována" jsou vybrány podle stejného principu). Pokud je funkce deklarována na globální úrovni, má přístup alespoň ke globálnímu scope. Samozřejmě platí, že parametry a lokální proměnné překrývají stejně pojmenované proměnné z venčí (tedy z lexikálního uzávěru).
Teď už můžeme dát dohromady, proč tento kód funguje:
function makeIntervalHandler(counter) {
return function() {
update(1,counter);
}
}
makeIntervalHandler vrací při zavolání funkci. Funkce je deklarována v jejím těle, takže má přístup i k jejímu parametru counter. A to i dávno po té, co je vrácena. Parametr counter překryje glonální proměnnou counter a číslo se v JS předá hodnotou, takže proměnná neodkazuje na stejnou hodnotu, jako globální counter. V closure se tak uchová hodnota z doby, kdy byla makeIntervalHandler zavolána.
updates[counter] = window.setInterval(makeIntervalHandler(counter), 10000);
Tady si zavolání makeIntervalHandler vyrobím funkci pro setInterval. Vrácená funkce bude volána až po uplynutí 10000ms, ale hodnotu předanou přes counter mám díky closure zafixovanou.
Asi to není tak jednoduché, jak bych chtěl. Ale scope v JavaScriptu a closure chtějí trochu času na pochopení. Pokud není něco jasné, klidně se zeptej.