Its common problem for such cases when you need to use sync processed data in async methods.
In you case you raise loop - its sync process, it increases i and run code you place text to closing bracket. So for increase i and run you code on each iteration. On every iteration you set new timeout, should be run in some time, its async. So what happening on first setTimeout start ? - Loop had already finished, i is already 10 and setTimeout use its callback.
To resolve this task you have to use closure - immediately invoke function witch be called on every iteration with i as param, and setTimeout inside this function. In this case param you passed will be stored in scope and could be used in timeout callback:
var timerNode = $('#timer'),
stepInSec = 1;
for (var i=10; i>=0; i--) (function(t) {
window.setTimeout(function() {
timerNode.text(t);
}, (10-t)*stepInSec*1000)
}(i))