Scopes in JavaScript. Different types of variable declarations.


You can think of a scope as of a wrapper that contains all the variables and a reference to the parent scope. What does that mean and what should we watch out for when dealing with it? Let’s find out!

How scopes work

When we try to access a variable in our code, the interpreter first looks for it in the current scope. If it wasn’t found, it goes up through the chain of scopes. At the very top of it, there is the global scope. Variables declared there can be both accessed and altered anywhere in the code. Global scope exists as long as your application runs and there is only one instance of it. There is another type of scope called a local scope that can enclose the variables that are declared inside of it. It exists as long as it is executed. JavaScript uses Lexical Scope, which means that every level of the scope chain has an access to the outer levels.


Let makes use of block scope. If you declare a variable with the let keyword, it will be accessible inside of a current block scope created with a block statement.

A block statement (or compound statement in other languages) is used to group zero or more statements.

We’ve all used it when writing if statements, or loops. Actually, you can even use standalone block statements.

In this example, when we tried to assign a value to a pet variable for the second time (    ), it was not present in the current scope, so the chain of scopes was traversed and the pet with a value dog was found and replaced with a cat. That’s why the pet value at the very bottom is a cat.

When the variable named pet was assigned a value for the third time (    ), the chain of scopes did not need to be traversed, because the variable named pet was declared with a let keyword in the current scope. That’s why the pet value at the very bottom is notlizard.


Const behaves the same as let when it comes to scopes. It is, as the name suggests, a constant.

  1. You need to initialize it with a value when declaring
  2. You can’t change its value

There is a thing to keep in mind though when it comes to the second point. If you assign an object to the variable, it actually stores just a reference to it. It means, that if you assign an object to a const variable, you can change its properties.


Back in the old days (before ES6) the only type of variable declaration keyword we had was var. Variables declared with var are function-scoped. It means, that declaring a variable with var makes it accessible throughout the whole function.

If this looks confusing to you, I used Immediately Invoked Function Expression (IIFE) here.

Global variables declared with the var keyword are attached to the window object (or the global object, if you are using Node.js). Even if you declare variables at the bottom of the function, they are going to be hoisted to the top (it does not happen with let and const).

When you see   you might think of that as one statement. JavaScript splits it in two:   and   . The first one will run before interpreting your code. Actually, both variables and functions are processed first, before any part of your code is executed.

There is a difference between the variable having a value of undefined, and not being defined, as the latter causes an error that stops the process of interpreting the code. It means that ‘Fluffy’ will not appear in the console at all!

Not using any keyword

If you don’t use any keyword at all when declaring a variable, the interpreter will traverse the scope chain just like in an ordinary value assignment. The only difference is that it won’t find a variable named ‘dog’ and it will create a global variable. This is considered a bad practice and is discouraged. It won’t work at all when in strict mode and will result in an error

Uncaught ReferenceError: dog is not defined

Other occurrences of block scope

There were a few situations where the block scope existed, even before ES6. ES3 specified the variable declaration in the catch clause of a try/catch to be block-scoped to the catch block.

Temporal Dead Zone

There is a catch to keep in mind when trying to access variables that might not have been defined yet. The only way to safely check if a variable was defined was to use typeof operator. Unfortunately, it causes problems with const and let variables.

ReferenceError from accessing let and const variables too early is called Temporal Dead Zone. Unfortunately, typeof behaves differently in this case and it is no longer safe to use it. It might be a good idea to declare let variables at the very top of the block to avoid it.

Let & for

Let has a special behaviour used in the head of a for-loop. It will cause variables declared in the head of the for loop to be declared for each iteration, not just once. Every time it will be initialized with the value from the end of the previous iteration.

Each index variable refers to the binding of one specific iteration and preserves the value. Therefore, each arrow function returns a different value. When it comes to var, the index variable will be declared once, and then modified.


In the current state of JavaScript, there is no reason to use var anymore, really. You should always use const if possible. If not, use let. This will help make your code readable, predictable and clean.

Notify of
Newest Most Voted
Inline Feedbacks
View all comments
5 years ago

Great article! Thanks a lot 🙂

2 years ago

Great article described differents between let and var. Thanks for that! Greetings.