Posts Let and Const Variable Scope in JavaScript
Post
Cancel

Let and Const Variable Scope in JavaScript

This is a quick note to keep in mind some interesting things about variable scope in JavaScript when declaring variables with let and const.

In JavaScript, variables declared with either let or const have block scope. Here are some examples:

1
2
3
4
5
{
  let a = 1;
}

console.log(a);  // Uncaught ReferenceError: a is not defined

This will raise an error because the variable a that was declared with let has a block scope and is only accessible from within the {...} block. Therefore, when we attempt to log the value of a outside of the block, an error is raised since no a variable has been defined in that outer scope.

This becomes more apparent when using if...then blocks. Unlike Ruby, where variables initialized within if...then blocks are accessible outside of the if...then block, in JavaScript they are not:

1
2
3
4
5
if (1 === 1) {
  let a = 1;
}

console.log(a);

Like the previous example, this code will also raise the same error since the variable a declared with let within the if {...} block has block scope and is not accessible outside of the block.

For comparison, in Ruby, even if the if statement branch is not evaluated, the variable is initialized with a nil value and is accessible outside of the if..then statement:

1
2
3
4
5
6
7
8
if true
  a = 1
else
  b = 1
end

p a, b   # 1, nil
p c      # NameError: Undefined local variable or method 'c' for main:Object

The local variable c above has not been initialized and an error is raised. Whereas, even though only the truthy branch of the if statement is evaluated, the local variable b is still initialized to nil.

As of far as I know now, variables declared in an outer scope in JavaScript seem to be available within inner scopes.

For example:

1
2
3
4
5
let a = 1;

if (1 === 1) {
  console.log(a);
}

1 is logged to the console since the truthy branch of the if {...} will always be evaluated.

Here’s another example, this time showing variable shadowing:

1
2
3
4
5
6
7
let a = 1;

if (1 === 1) {
  let a = 2;
}

console.log(a);

This also logs 1 to the console. The second declaration of the a variable within the if {...} block shadows the first declaration of the a variable. Therefore, the second declaration is only accessible from within the if {...} block. In this case, it’s not being used. Once we evaluate the console.log statement on line 7, the variable a that’s in scope at that time has a value of 1 from the let variable declaration on line 1.

Using const to declare a variable is similar, but these variables cannot be reassigned like variables declared with let:

1
2
3
4
5
const A = 1;

if (1 == 1) {
  A = 2;       // Uncaught TypeError: Assignment to constant variable.
}

Yet, constants can be declared within an inner block scope, like let, shadowing constants declared in an outer scope:

1
2
3
4
5
6
7
8
const A = 1;

if (1 == 1) {
  const A = 2;
  console.log(`Value of A in inner scope: ${A}`);
}

console.log(`Value of A in outer scope: ${A}`);
1
2
Value of A in inner scope: 2
Value of A in outer scope: 1

While this may seem simplistic in terms of programming in general, understanding the scope of variables will likely come in handy when debugging more complicated code later on.

This post is licensed under CC BY 4.0 by the author.