var, let, and const in JavaScript: Scope, Hoisting, Redefinition, and Reassignment
In the past, we used the var
keyword to create new variables. Modern JavaScript introduces two new ways to declare variables: let
and const
.
Today, we'll discuss the differences between them. To do that, let's first talk about the differences between let
and var
.
let vs var
Let's discuss the var
keyword first.
Variables declared with var
can have either global or local scope. Global scope applies to variables declared outside of functions, while local scope applies to variables declared inside functions.
var greet = "Hello"; console.log(greet); // Hello
In the example above, I've declared greet
as a global variable. This global variable greet
can also be used within a function, like this:
var greet = "Hello"; function sayHello() { console.log(greet); } sayHello(); // Hello
However, the reverse is not true. If I declare a variable inside a function, I cannot use it outside the function.
function sayHello() { var greet = "Hello"; console.log(greet); } sayHello(); // Hello console.log(greet); // Uncaught ReferenceError: greet is not defined
So, we can conclude that var
is function-scoped. This means that a variable created with var
in a function will only exist within that function.
If the variable is created outside of the function, it will exist in the outer (global) scope.
var greet = "Hello"; // global scope function sayHello() { var greet = "Hi"; // local scope console.log(greet); } sayHello(); // Hi console.log(greet); // Hello
Variables declared with var
can also be redeclared.
var greet = "Hello"; console.log(greet); // Hello var greet = "Hi"; console.log(greet); // Hi
Also, variables declared with var
are hoisted to the top of their function or global scope, which means they are accessible before the line where they are declared.
console.log(greet); // undefined var greet = "Hello"; console.log(greet); // Hello
let
, on the other hand, is block-scoped. This means whenever a variable is created with let
, it will only exist within its block.
But wait, what’s a block?
A block in JavaScript is anything within a pair of curly braces. The following are examples of blocks.
{ // new scope block } if (true) { // new scope block } while (true) { // new scope block } function () { // new block scope }
The difference between block-scope
and function-scoped
variables is huge. When you use a function-scoped
variable, you may accidentally overwrite a variable without intending to do so. Here’s an example:
var greet = "Hello"; if (true) { var greet = "Hi"; } console.log(greet); // Hi
In this example, you can see that greet
becomes Hi
after running through the if block.
As you can see, block-scoped
variables make development much simpler by removing common gotchas with function-scoped variables. To make life simple, I recommend you use let
over var
whenever you declare JavaScript variables from now on.
Just like var
, variables declared with let
can be reassigned to other values, but they cannot be redeclared.
let greet = 'Hello` console.log(greet) // Hello greet = 'Hi' console.log(greet) // Hi
Variables declared with let
are also hoisted to the top of their global, local, or block scope, but their hoisting is a little different from the one with var
.
var
variables are hoisted with a default value of undefined
, which makes them accessible before their line of declaration (as we've seen above).
But, let
variables are hoisted without a default initialization. So when you try to access such variables, instead of getting undefined, or variable is not defined error, you get cannot access variable before initialization
. Let's see an example:
console.log(greet); // ReferenceError: Cannot access 'greet' before initialization let greet = "Hello";
Now we know what let
does, let’s move on to the difference between let and const.
let vs const
Like let
, const
is also blocked-scoped. The difference is that const cannot be reassigned once declared.
const greet = "Hello"; greet = "Hi"; // TypeError: Assignment to constant variable. let greet1 = "Hello"; greet1 = "Hi"; console.log(greet1); // 'Hi'
Since const
cannot be reassigned, they’re good for variables that would not change.
When declaring variables, I always prefer const
over let
whenever possible because I receive the extra cue that the variable would not get reassigned. Then, I use let for all other situations.
Summary
Here's a table summary showing the differences between these keywords:
Get my free, weekly JavaScript tutorials
Want to improve your JavaScript fluency?
Every week, I send a new full-length JavaScript article to thousands of developers. Learn about asynchronous programming, closures, and best practices — as well as general tips for software engineers.
Join today, and level up your JavaScript every Sunday!
Thank you, Taha, for your amazing newsletter. I’m really benefiting from the valuable insights and tips you share.