The var
keyword was the original keyword used to declare variables in JavaScript.
Introduced in ES2016, let
and const
are two new keywords used for declaring variables. This article will explain the differences between how the var
, let
, and const
keywords work.
Before we jump into the differences between let
, var
and const
, it's important to understand how scope and hoisting works.
Scope
Scope is the space where the value of a variable is defined and accessible.
There are 3 types of scope in JavaScript:
- Global Scope
- Function Scope
- Block Scope
Variables defined with the var
keyword have either global or function scope.
Variables defined with the let
or const
keyword have block scope.
For a more in-depth explanation of scope, see my other post titled Scope in JavaScript.
Hoisting
When a JavaScript program runs, it will first parse the script and look for any variable declarations or function declarations. If it finds any variable or function declarations, it will "hoist" those to the top their respective scopes and process them first before proceeding to evaluate the rest of the JavaScript code. This process is called "Hoisting"
Hoisting affects variable declaration but NOT value INITIALIZATION / ASSIGNMENT.
Examples of Hoisting in JS
x = 1; // Assign the variable x a value of 1
console.log(x); // 1;
// Declare a variable x
// This declaration will be "hoisted" by JS when the program runs
var x;
x = 1;
var x; // This gets hoisted
// same as
var x;
x = 1;
Remember, hoisting only applies to variable declarations, not variable initialization. The below example will return "undefined" as x is initialized and not defined in the second line and therefore, it is not hoisted above the console.log()
call.
console.log(x); // returns undefined
var x = 1;
The code below will print 2. Since the variable y is declared on line 3, but not initialized, it will be hoisted up to the top of the program, above the y = 2
initialization. So by the time console.log(y)
is actually called, a value of 2 will be defined for y
.
y = 2;
console.log(y); // Returns 2
var y;
// Same As
var y;
y = 2;
console.log(y);
NOTE: While hoisting applies to variables declared with var
, let
, or const
, hoisting really only helps variables declared with var
. Variables declared with the let
keyword return ReferenceError
if they are un-initialized (see TDZ
section further down for more detail). You also cannot declare a variable with the const
keyword without also initializing it's value right away. If you try to do this, you will obtain a "SyntaxError: Missing initializer in const declaration".
Differences between var, let, and const
var
A variable which is declared (but not initialized) using the var
keyword returns a value of undefined
if it is accessed before it is initialized (see section about hoisting).
console.log(x); // Returns undefined
var x = 1; // variable declaration and initialization
console.log(x); // Returns 1
Variables declared with var
can be either function or global scoped.
// Variable declared in global scope
var globalVariable = "This variable was declared in the global scope";
function myFunc() {
// Variable declared in function scope
var funcVariable = "This variable was declared in the function scope";
}
Variables declared with var
can be re-declared.
var x = 1;
console.log(x); // 1
var x = 2;
console.log(x); // 2
let
Variables declared with let
are block scoped. We can only declare variables with the same name as long as they are in different block scopes using let
.
{
// This x variable does not exist outside of the current block scope
let x = 1;
console.log(x); // 1
}
// Trying to access x outside of its function block
console.log(x); // Uncaught ReferenceError: x is not defined
{
// Since we are now in a new block scope, we can declare a variable named x (note that this is NOT the same variable as what was declared in the block above)
let x = 2;
console.log(x); // 2
}
// Trying to access x outside of its function block (still does not exist)
console.log(x); // Uncaught ReferenceError: x is not defined
Unlike var
, variables declared with the let
keyword cannot be re-declared within the same scope
let x = 1;
let x = 2; // Uncaught SyntaxError: Identifier 'x' has already been declared
You can however, still redefine (reassign) a variable declared with let
.
let x = 1;
console.log(x); // 1
x = 2; // This is ok because you are not trying to redeclare x, just redefine its value
console.log(x); // 2
The Temporal Dead Zone
The Temporal Dead Zone (TDZ) is the area in the current scope between the start of the scope and where the variable is finally initialized. The TDZ applies to variables declared with the let
keyword. A variable declared with let
cannot be accessed (will return "ReferenceError") within the TDZ.
{
// Start of Temporal Dead Zone for variable x
console.log(x); // ReferenceError, still in TDZ for x
var y = "hi"; // Still in TDZ for x
let x; // x declared, but not initialized with value, still in TDZ for x
x = 10; // TDZ for x ended as x is initialized to a value of 10
}
const
Similar to variables declared with let
, variables declared with the const
keyword are block scoped.
Also similar to let
, variables declared with const
cannot be redeclared.
Unlike variables declared with let
however, variables declared with const
MUST be initialized right away. If not, you will end up with a "SyntaxError: Missing initializer in const declaration" error.
Most importantly, variables declared and initialized with the const
keyword cannot have their value changed through reassignment (see note below). This is because the const
keyword causes the name of the variable to be read-only, preventing write access to the value stored in memory through the assigned variable. If you think about it, it makes sense why this is. If you want to create a variable that can't be changed easily, you need to know it's value, otherwise, you would just end up with a constant variable with an "undefined" value.
NOTE: Notice that variables initialized with the const
keyword cannot have their value changed through reassignment. This does not mean that the value of a constant value cannot change, it only means you can't change it using the variable name directly. While there isn't another way to change a string or number variable other than reassignment for example, you can change the properties of an object.
// Create a variable using the const keyword and assign it a value of 1 (number)
const x = 1;
x = 2; // SyntaxError: Missing initializer in const declaration
// Create aa variable using the const keyword
// and assign it to an object
const myObj = {
favoriteFood: "Pizza",
favoriteLanguage: "JavaScript",
favoriteHobby: "coding",
};
// Print out the value of favoriteFood
console.log(myObj.favoriteFood);
// Change the value of favoriteFood
// This works because we are not accessing the value directly through the use of the value name
myObj.favoriteFood = "Brocolli";
console.log(myObj.favoriteFood);
Which variable declaration is best and which should I use?
I read an article from Wes Bos and I like his advice:
- Use the
const
keyword to declare variables by default unless you know that your variable will need to have its value changed (uselet
in that case). - Use the
let
keyword to declare a variable if you know its value will change (like an iterator for example). - Unless necessary for a special case, avoid using the
var
keyword for variable declaration.
Summary: Difference between variables declared with "var", "let", and "const" keywords:
var
- Scope:
- Global
- Function
- Able to be redeclared?
- Yes
- Able to be reinitialized?
- Yes
let
- Scope:
- Global
- Block
- Able to be redeclared?
- No
- Able to be reinitialized?
- Yes
const
- Scope:
- Global
- Block
- Able to be redeclared?
- No
- Able to be reinitialized?
- No
Resources
- MDN - var
- MDN - let
- MDN - const
- MDN - block
- MDN - window
- MDN - Variable Scope
- MDN - Block Statement
- MDN - Hoisting
- MDN - Variable Hoisting
- Var, Let, and Const - What's the Difference?
- W3 Schools - JavaScript Scope
- Eloquent JavaScript, A Modern Introduction to Programming
- JavaScript Variable Declaration and Initialization
- What is the Tempral Dead Zone?
- Wes Bos - Variables and Statements
Top comments (1)
hello,you say
''' A variable declared with let cannot be accessed (will return "ReferenceError") within the TDZ. '''
but how to explain
let b;
console.log(b); // undefined
b = 5;