DEV Community

Cover image for Modern JS Discussion: var/let/const
Kenta Takeuchi
Kenta Takeuchi

Posted on • Originally published at bmf-tech.com

Modern JS Discussion: var/let/const

This article was originally published on bmf-tech.com.

※This article is a reprint from the Innovator Japan Engineers’ Blog.

What is Scope

Before diving into the main topic, let's review the definition of scope.

Scope refers to the range within which variable names and function names can be referenced.

There are various types of scopes, but here we will explain mainly three types of scopes in a table.

Scope Name Range Remarks
Global Outside of functions Accessible from anywhere.
Local (Function) Inside of functions Accessible only from within the local scope.
Block Inside of blocks ({ }) if, for, switch, etc.

Block scope was not originally available in JavaScript, but with the introduction of let and const, block scope can now be used.

About var, let, const

var

Redeclaration Reassignment Scope
Local

var allows both redeclaration and reassignment.

var a = 1;
var a = 2;  // Redeclaration possible

function sayNum()
{
  a = 100; // Reassignment possible
  return a;
}

console.log(sayNum()); // 100
Enter fullscreen mode Exit fullscreen mode

Previously, var was the only way to declare variables, but with the introduction of let and const, there is almost no need to declare variables with var anymore. Except for some special cases, performance tuning, or browser compatibility considerations, the opportunity to use var is almost nonexistent.

Hoisting

var has a concept called hoisting, which means that variable declarations are processed before the code execution.

This is processed as follows:

a = 1;
var a;
Enter fullscreen mode Exit fullscreen mode

It is processed like this:

var a;
var a = 1;
Enter fullscreen mode Exit fullscreen mode

Incidentally, if you try the same code with let or const...

let a;
let a = 1; // Uncaught ReferenceError: a is not defined
Enter fullscreen mode Exit fullscreen mode

In the case of let, a ReferenceError is thrown, but hoisting itself actually occurs. This is the same for const.

In ECMAScript 2015, let lifts variables to the top of the block. However, referencing the variable before the declaration causes a ReferenceError. The variable is in a "temporal dead zone" from the start of the block until the variable declaration is executed.

Quoted from MDN - let

This is the same for const.

All concerns about the "temporal dead zone" for let apply to const as well.

Quoted from MDN - const

a = 1;
const a; // Uncaught SyntaxError: Missing initializer in const declaration
Enter fullscreen mode Exit fullscreen mode

In the case of const, a syntax error is thrown unless initialization (const a = 1;) is performed.

Let's check the hoisting of const.

const a = 1;

function sayNum()
{
  console.log(a); // Uncaught ReferenceError: a is not defined
  const a = 100;
}

sayNum();
Enter fullscreen mode Exit fullscreen mode

There seem to be few scenes where hoisting is consciously used, but it seems better to remember that the hoisting behavior differs between var, let, and const.

let

Redeclaration Reassignment Scope
✗ (Redeclaration in the same scope) Block

let does not allow redeclaration but allows reassignment.

let a = 1;
let a = 2; // Uncaught SyntaxError: Identifier 'a' has already been declared   => Redeclaration in the same scope not allowed
Enter fullscreen mode Exit fullscreen mode
let a = 1;

function sayNum()
{
  a = 100 // Reassignment possible
  return a;
}

console.log(sayNum()); // 100
Enter fullscreen mode Exit fullscreen mode

The scene to use let is where var was used before, but it is particularly limited to parts where reassignment is possible.

const

Redeclaration Reassignment Scope
✗ (Redeclaration in the same scope) Block

const does not allow either redeclaration or reassignment.

const a = 1;
const a = 2; // Uncaught SyntaxError: Identifier 'a' has already been declared => Redeclaration in the same scope not allowed
Enter fullscreen mode Exit fullscreen mode
const a = 1;

function sayNum()
{
  a = 100 // Uncaught TypeError: Assignment to constant variable. => Reassignment not allowed
  return a;
}

console.log(sayNum()); // 100
Enter fullscreen mode Exit fullscreen mode

Summary

Declaration Redeclaration Reassignment Scope
var Local
let ✗ (Redeclaration in the same scope) Block
const ✗ (Redeclaration in the same scope) Block

Basically, it seems good to declare variables using const and use let for parts where reassignment is possible, and consider var for other special cases. Variable scope pollution can lead to bugs and hinder code reading, so we want to use them properly!

Reference Links

Top comments (0)