Steve Jones - SSC Editor (9/16/2013)
If someone has a good explanation that makes sense, I'm happy to change it.
The batch is processed in two phases.
Phase one is parsing. This works top to bottom and ignores all control-flow. That's why, if you declare the same variable in a THEN and ELSE, it will raise an error for declaring it twice, even though always exactly one will execute. And that's why, if you declare a variable in a loop that runs multiple time, it will not raise an error. The parser simply reads the text top to bottom, and the only requirement is that references to the variable are "below" the declaration.
Phase two is execution. This phase respects control-flow, but not variable declaration.
I don't know if there are any references for this, and I don't have the time to look for them now.
EDIT: Forgot to add that while this may be interesting to know, bast practice is to put all declarations at the start of a code block, before any executable statements. (Mixing the two in the form of assignment on declaration is okay. Remember that "DECLARE @i int = 0;" is actually just shorthand for "DECLARE @i int; SET @i = 0;" to understand how it behaves).