Block scope with
var at lot. And mostly it works the way you expect it to.
But you can run into strange bugs if you forget (or never knew) that
var doesn’t create block-scoped variables the way other languages do.
var is scoped to its containing function (or global), not its containing block. This is big difference if you’re used to… well, almost any other language.
let solves this problem.
Here’s a quick refresher on how
var’s function scope works:
happy is available everywhere in the highlighted area – notably, it is still in scope after (and before) the block it’s declared in.
Now, here’s the same example using
let, which has block scope:
See how the highlighted area is confined to that single
if block? This will be familiar to those coming from other languages where block scope is the norm. Block scope helps avoid subtle bugs.
let to declare the index in a
for loop now works “as expected” (if you’re familiar with C/C++/Java/C#/…):
var, where declaring that variable at the top of the
for loop actually leaves it in scope after the loop is done:
let, doing the sensible thing, confining the variable to the loop because of block scope:
Closures in loops
Here’s a weird side effect of using
var inside a closure that’s created inside of a loop. This could happen if you, say, want to set up a bunch of timers:
It prints “3”, 3 times… instead of the expected “0, 1, 2”. WAT? What’s going on?
Closures capture the values from the current scope. But not like a snapshot in time… more like a reference to a variable name. Since the scope is the same each time a closure is created, all 3 closures reference the same variable.
let fixes this:
Alright, let’s talk about
const (see what I did there?).
const is block-scoped, just like
let. The only difference is that it can’t be reassigned or redeclared.
You also must give it a value at declaration time.
const variables can’t sit around unassigned. No “first assignment wins” here.
Notice I said things declared as
const can’t be reassigned.
I didn’t say they couldn’t be changed… the value of a
const is not immutable.
This only applies to Objects, Arrays, and Functions, though – they’re the only mutable types in JS. If you declare a
const Number, String, Boolean, Null, Undefined, or Symbol (new to ES6), those are primitive types and they will in fact be immutable.
For the C/C++ folks: ES6
const is like a constant pointer to an object rather than a pointer to a constant object.