var
The var
statement declares a variable in JavaScript which abides to the following rules:
- is function-scoped or globally-scoped.
- is not subject to the temporal dead zone.
- it creates a global property on
window
with the same name. - is reassignable.
- is redeclarable.
Function-scoped or globally-scoped
var
creates a global variable when appears in the global scope. In addition, it creates a global property on window
with the same name:
var city = "Florence";
console.log(window.city); // "Florence"
When declared inside a function, the variable is scoped to that function:
var city = "Florence";
function bubble() {
var city = "Siena";
console.log(city);
}
bubble(); // "Siena"
console.log(city); // "Florence"
var
declarations are subject to hoisting:
function bubble() {
city = "Siena";
console.log(city);
var city; // hoists
}
bubble(); // "Siena"
Accidental global variables
Variables assigned without any statement, be it var
, let
, or const
, become global variables by default:
function bubble() {
city = "Siena";
console.log(window.city);
}
bubble(); // "Siena"
To neutralize this behaviour we use strict mode:
"use strict";
function bubble() {
city = "Siena";
console.log(window.city);
}
bubble(); // ReferenceError: assignment to undeclared variable city
reassignable and redeclarable
Any variable declared with var
can be later reassigned, or redeclared. An example of redeclaration:
function bubble() {
var city = "Florence";
var city = "Siena";
console.log(city);
}
bubble(); // "Siena"
An example of reassignation:
function bubble() {
var city = "Siena";
city = "Florence";
console.log(city);
}
bubble(); // "Florence"
let
The let
statement declares a variable in JavaScript which abides to the following rules:
- is block scoped.
- is subject to the temporal dead zone.
- it does not create any global property on
window
. - is reassignable.
- is not redeclarable.
Block scoped
A variable declared with let
does not create any global property on window
:
let city = "Florence";
console.log(window.city); // undefined
When declared inside a function, the variable is scoped to that function:
let city = "Florence";
function bubble() {
let city = "Siena";
console.log(city);
}
bubble(); // "Siena"
console.log(city); // "Florence"
When declared inside a block, the variable is scoped to that block. An example with the block statement:
let city = "Florence";
{
let city = "Siena";
console.log(city); // "Siena";
}
console.log(city); // "Florence"
An example with an if
block:
let city = "Florence";
if (true) {
let city = "Siena";
console.log(city); // "Siena";
}
console.log(city); // "Florence"
var
instead, doesn't care about blocks:
var city = "Florence";
{
var city = "Siena";
console.log(city); // "Siena";
}
console.log(window.city); // "Siena"
Temporal dead zone
let
declarations are subject to hoisting, but temporal dead zone kicks in:
function bubble() {
city = "Siena";
console.log(city); // TDZ
let city;
}
bubble();
// ReferenceError: can't access lexical declaration 'city' before initialization
Temporal dead zone prevents access to let
declarations before their initialization. Another example:
function bubble() {
console.log(city); // TDZ
let city = "Siena";
}
bubble();
// ReferenceError: can't access lexical declaration 'city' before initialization
We can see that the exceptions are the same in both examples: the proof that temporal dead zone kicked in.
Further resources on the topic: Temporal dead zone demystified.
Reassignable, not redeclarable
Any variable declared with let
can't be redeclared. An example of redeclaration which throws:
function bubble() {
let city = "Siena";
let city = "Florence";
console.log(city);
}
bubble(); // SyntaxError: redeclaration of let city
An example of valid reassignation:
function bubble() {
let city = "Siena";
city = "Florence";
console.log(city);
}
bubble(); // "Florence"
const
The const
statement declares a variable in JavaScript which abides to the following rules:
- is block scoped.
- is subject to the temporal dead zone.
- it does not create any global property on
window
. - is not reassignable.
- is not redeclarable.
Block scoped
A variable declared with const
does not create any global property on window
:
const city = "Florence";
console.log(window.city); // undefined
When declared inside a function, the variable is scoped to that function:
const city = "Florence";
function bubble() {
const city = "Siena";
console.log(city);
}
bubble(); // "Siena"
console.log(city); // "Florence"
When declared inside a block, the variable is scoped to that block. An example with the block statement {}
:
const city = "Florence";
{
const city = "Siena";
console.log(city); // "Siena";
}
console.log(city); // "Florence"
An example with an if
block:
const city = "Florence";
if (true) {
const city = "Siena";
console.log(city); // "Siena";
}
console.log(city); // "Florence"
Temporal dead zone
const
declarations are subject to hoisting, but temporal dead zone kicks in:
function bubble() {
console.log(city);
const city = "Siena";
}
bubble();
// ReferenceError: can't access lexical declaration 'city' before initialization
Not reassignable, not redeclarable
Any variable declared with const
can't be redeclared, nor reassigned. An example of redeclaration which throws:
function bubble() {
const city = "Siena";
const city = "Florence";
console.log(city);
}
bubble(); // SyntaxError: redeclaration of const city
An example of reassignation which trows as well:
function bubble() {
const city = "Siena";
city = "Florence";
console.log(city);
}
bubble(); // TypeError: invalid assignment to const 'city'
Top comments (2)
Hello, may I translate your article into Chinese?I would like to share it with more developers in China. I will give the original author and original source.
Covered most of the scenarios and the top diagram would be quite effective to start. But I can say from my experience, Its really tricky to understand TDZ.