`let`s and `const`s incur a significant performance penalty.

Is that still true? Early versions of V8 would do scope checks for things that weren't declared with var but it doesn't do that any more. I think const and let are lowered to var representation at compile time now anyway, so when the code is running they're the same thing.

I'm sure it can do that in many cases. But if the scopes are a bit complicated, and in particular when variables are captured in lambdas, it's just not possible. The semantics require the TDZ behavior. If you can statically analyze that the TDZ won't be triggered, you can lower to `var`, but otherwise you have to keep the checks.