Knowing the difference between let and var in JavaScript is something that you will need to learn and know if you work with JavaScript for enough time.
Not only will it come up in interviews, but it will also save you having some strange errors and issues when developing.
For most cases the main reason to use a let or var statement in JavaScript is because you need to be able to redefine the value at a later point, and if you don’t then you could use a const statement instead.
But aside from that, how then does a let or var statement fit into this, and can, and should you still use it even now?
In this post we are going to cover everything you need to know to learn the difference between let and var in JavaScript as well as which one you should use.
What is the difference between let and var in JavaScript?
The main difference between let and var in JavaScript for most use cases is that a let statement is block-scoped whereas a var statement is function-scoped, or globally scoped.
This means that not only can a let not be globally-scoped, but it also means that a let will be more restricted to where it can be accessed which is a good thing.
One of the main reasons why the let statement was added into JavaScript was to prevent bugs because of how the function-scoped var statement is confusing to use.
Simply put, function-scopes are more confusing than block-scopes because of how we expect them to behave.
Here is a list of all the differences between a let and a var in JavaScript:
- Scoping and Variable scopes
- Hoisting and The Temporal dead zone
- Creating global object property
- Redeclaration
- Emulating private members (private variables)
- The naming of let vs var
Let’s now take a look into these differences between let and var in more detail.
Scoping and Variable scopes
When using a let statement or a var statement in JavaScript both have different rules when it comes to scoping, the var statement is function-scoped and the let statement is block-scoped.
To understand what that means, we need to look at what a block is in comparison to a function.
As you might expect, a function is just a normal function that you will find in JavaScript:
Here is how a function looks:
function exampleFunction() {
// code in here
}
As you can see there is nothing strange about this, and when we talk about how a var is function-scoped, all it means is that when you define a var statement inside of a function it will have access to all scopes and child scopes within the function but it will not be able to be access scopes outside of the function.
Blocks are a little different to functions in JavaScript and here is how a block looks:
{
// code in here
}
As you can see a block is simply defined by the use of curly braces in JavaScript, and what this means is that any time you use a curly brace in JavaScript you are creating a new block scope, this can be for an if statement, a for loop, a function, and more.
You can even just use curly braces by themselves to create a standalone block of code.
When we define a let within a block it behaves the same way a var would when we define it in a function when considering the scope.
The let will have access to all scopes and child scopes within the block it has been defined in.
One of the ways this affects JavaScript in practice is when looking at for loops.
Because a for loop uses a block and not a function when you use a var statement in a for loop all of those variables get leaked out into the current scope which causes a lot of bugs and confusion.
Here is a visual representation of how a for loop would look using a var as a while loop to make it easier to see what would be happening:
{
var i = 0
while (i < 5) {
console.log(i) // 0, 1, 2, 3, 4, 5
i += 1
}
}
console.log(i) // 5
In reality, the var actually is defined within the block, but because the var ignores the block where it is not a function it acts the same way as if we defined it outside of the block.
As you can see the i
variable has now leaked out and this can cause issues.
Let’s now look at a visual representation of using a let statement with a while loop to see the differences:
{
let i = 0
while (i < 5) {
console.log(i) // 0, 1, 2, 3, 4, 5
i += 1
}
}
console.log(i) // Uncaught ReferenceError: i is not defined
Now in the above example when using a let statement you can see that we have added in a block to contain the variable i
.
Because of this in combination with the use of the let statement the variable is no longer leaked out into the current scope which prevents many issues.
To be clear, if you replace the let statement in the above we will go back to having the same issue of the variable being leaked out into the current scope because of how a var is function-scope and not block-scoped.
{
var i = 0
while (i < 5) {
console.log(i) // 0, 1, 2, 3, 4, 5
i += 1
}
}
console.log(i) // 5
Hoisting and The Temporal dead zone
Hoisting is the process in which the JavaScript engine will lift/hoist a variable to the top of a scope and assign space to it.
When using a var statement the engine will also implicitly define the empty var variable as undefined
which allows us to be able to access and use this variable before the actual definition of it in our code.
The difference between a var and a let in this scenario is that a let statement will not be implicitly defined as undefined
and will therefore give us a reference error when trying to access it before the declaration.
This is known as the temporal dead zone (TDZ).
Here is how the temporal dead zone looks in JavaScript:
function example() {
console.log(myVar) // undefined
console.log(myLet) // ReferenceError: Cannot access 'myLet' before initialization
var myVar = "Hello"
let myLet = "World"
console.log(myVar) // "Hello"
console.log(myLet) // "World"
}
Creating global object property
When you use a var statement at the upper most level or scope it will create a global variable.
For example in the browser if you create a var at the uppermost level you will be able to access it by looking it up on the window object.
If you try to do the same thing with a let statement however, this won’t happen and you won’t be able to find it on the window object because it has not been created as a global variable.
Here is an example of creating global object property with var vs let:
var testVar = "Hello"
let testLet = "World"
console.log(window.testVar) // "Hello"
console.log(testVar) // "Hello"
console.log(window.testLet) // undefined
console.log(testLet) // "World"
Redeclaration
When you redeclare a variable using the var statement JavaScript will allow it to be redeclared, but when you try to do the same with a let statement it will throw an error.
What this means is when using the keywords let or var, with let you can only use it on the initial declaration but with var you can keep using it.
For example:
var test = 1 // 1
var test = 10 // 10
test = 20 // 20
let example = 1 // 1
// let example = 10 // Uncaught SyntaxError: Identifier 'example' has already been declared
example = 20 // 20
Emulating private members (private variables)
By using a combination of blocks, var statements and let statements you can emulate private members/variables.
For the most part you won’t want to do this because it could be a little confusing and instead the standard way to do this in JavaScript would be to either use a Class or a closure.
But it is possible to do with a combination or blocks, let’s and var’s.
Here is an example of how you can do this:
var Example
{
let privateVariable = "Private"
var publicVariable = (Example = function () {
this.public = "Public"
})
Example.prototype.getPrivate = function () {
return privateVariable
}
}
console.log(privateVariable) // ReferenceError: privateVariable is not defined
const example = new Example()
console.log(example) // { public: "Public" }
console.log(example.getPrivate()) // "Private"
As you can see in the above example, the privateVariable that we have created using a let is now private and can only be seen within the object itself because of the block.
The naming of let vs var
The last difference between let and var is a more obvious one, and that is the naming.
The let statement is initialized by starting a variable with let
and var with var
.
The var statement as you might have guessed is just a shortened version of variable
.
What does let standfor and mean in JavaScript
The let statement is named let
because it is a way of asking the computer to allow or let a variable be defined as a value.
It comes from English where let or letting is a way to allow or permit something.
For example if defining a variable as a let was a sentence then it would read something like:
Engine, please let this variable named as "example" be set to "some value".
Should I use let or var?
Generally speaking you should aim to use let over var every time unless you have a specific reason why you need to use a var.
For 99.9999% of the time you will not ever need to use a var in your code so it can be avoided which means you should avoid it.
The let statement was introduced to reduce bugs from using var because of the function-scope being confusing.
If you have a variable that will not need to change, then you should use a const which means constant.
If you have a variable that will need to change then you should use a let.
If you absolutely need a global variable, you should directly add it in as a property of the global object.
Block scope vs Function scope
As we have discussed, the main difference between a var and a let is the block-scope vs function-scope.
Just to go over this one last time, a function-scope is scoped to a normal JavaScript function meaning the variable cannot access any parent scope outside of the function it is declared in.
A block-scope is scoped to a block in JavaScript that is defined by curly braces which means that any block scoped variable within the block cannot access any parent scope outside of the block it has been created in.
Summary
There we have what is the difference between let and var in JavaScript, if you want more like this be sure to check out some of my other posts!