Var vs Let vs Const in Javascript
So recently I've been updating my javascript skills with a little node action and I came across the a few things that I hadn't noticed before in javascript. Both of these revolve around the let keyword and the var keyword.
The Deal With var
Everyone knows you should put var in front of your keywords when doing javascript. I mean it's basically folk wisdom at this point. I mean you just do it right?
What I found out is what it actually does, is this: what the compiler actually does is put the variable at the top of the function scope
Here's an example:
var awesome, things
for (var i=0; i < 10; i++){
var lessThanawesome = i * 5
console.log(i, lessThanAwesome)
}
If you were to actually run this code, you'd get this strange error
Uncaught ReferenceError: lessThanAwesome is not defined
The issue is with your variable assignment. var
is hoisted to the top of the scope (outside your for
loop) and is initialized before var i
is assigned. ... which leads to our awkward error.
Fix it with es5
If we wanted to fix this, we would need to initialeze the lessThanAwesome
variable outside the scope and then use it inside the loop.
var awesome, things, somewhatMoreAwesome
for (var i=0; i < 10; i++){
var somewhatMoreAwesome = i * 5
console.log(i, somewhatMoreAwesome)
}
Getting Let Down
So var
can be a bit unexpected. But new in ES6, there is now the ability to have variables that are scoped to the block. If you want to do that, you need to let var
go and get in with let
.
Here's the following code with the new let
syntax:
var awesome, things, awesome
for (var i=0; i < 10; i++){
var awesome = i * 5
console.log(i, awesome)
}
Caveat Emptor
There are a few other differences to watch for when using the fancy new let
keyword.
can't let this go
First, if you use let
at the top level of a function, it will not not create a property on the global object. What this means is that you will not be able to access this.var
.
Consider the following example (borrowed from MDN):
var x = 'global';
let y = 'global';
console.log(this.x); // returns 'global'
console.log(this.y); // returns undefined
Temporal Deadzones
let
won't allow you to define the same variable twice in the same scope.
if (x) {
let foo;
let foo; // TypeError thrown.
}
This means that switch statements will get angry as well, since there is only 1 underlying scope for the block
switch (x) {
case 0:
let foo;
break;
case 1:
let foo; // TypeError for redeclaration.
break;
}
Constantly using Const
After some time, you'd think let would be your best friend. But it turns out that most of the time you don't want your variables to be variable. Idempotent content makes things much easier to reason about. So default to const, unless you have a good reason to reassign a variable.
This will still let you assign members to objects and add items to arrays, since the identity of the object is the same. Just go with it.
References
- Mozilla Developer Reference #var
Great intro with solid examples. - MDN Reference for #let More examples and explanations for let.
- http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
Good overview of variable hoisting and intro to scope in javascript - http://www.ecma-international.org/ecma-262/5.1/#sec-10.3
Not for the faint of heart (or for people who really like technical specs)