foo is indeed going to be undefined, unless the condition is met, but it won't throw any exceptions, you'll just get an undefined value if you use foo in any expression. In your example it is a matter of better style: you're declaring a variable inside of if block, but plan to use it outside. Sure, it'll be hoisted and created anyway, but it just makes code less explicit and less readable. In this case it's indeed better to declare it at the top of function.
I won't comment on how ES6 let and const work, as other people already described that. Instead I'd like to note, that if you find yourself writing functions with multiple blocks, each using it's own multiple block-scoped variables, I'd strongly suggest splitting your function into smaller functions with descriptive names. That will make your code so much more readable. Having let and block scope is nice, but it doesn't mean you should always use them. :)