

let and const) restricts variable visibility to code blocks, unlike var, which is function-scoped.
Understanding JavaScript scope is essential for writing even the simplest programs. While seemingly straightforward, this topic has numerous nuances that confuse many beginners. Most of these nuances fade into obscurity once developers switch from using var to let and const.
Does that mean the topic can be skipped? Absolutely not. Thorough mastery of scope mechanics is frequently tested during job interviews.
By understanding a few simple rules, you can significantly increase your chances of landing your dream job.
In programming languages, scope refers to the set of rules governing how variables are stored and looked up within a program.
JavaScript uses lexical scope, meaning that the location where variables and functions are declared during compile time determines their scope.
Think of scope as a set of nested containers - each block, function, or module represents a container that determines where variables can be accessed.
JavaScript engines perform two types of lookups when working with variables, depending on the context:
Happens when a variable is on the left side of an assignment operation. The engine searches for a memory location to store the value.

Here, the engine finds or creates a place to store the value 42.
Happens when a variable's value is being accessed.

The engine retrieves the value of foo to pass to console.log.
JavaScript behaves differently depending on whether strict mode is enabled:

Lexical scope refers to how JavaScript determines the scope of a variable based on its location in the source code. Consider this example:

Here, bar logs 2 because it looks at the scope where it was defined (global), not where it was called. If you’ve ever been puzzled by this behavior in JavaScript, you’re not alone - it’s a common "aha!" moment for many developers.
Block scope allows variables to exist only within a specific block (e.g., if, for). With let and const, JavaScript introduced true block scoping:

In contrast, var is function-scoped, meaning its scope extends to the entire function:

Hoisting is JavaScript’s behavior of moving declarations to the top of their enclosing scope. However, only the declaration is hoisted - the initialization remains in place.
Example:

This behaves as if rewritten to:

To avoid confusion, always declare variables at the top of their scope or use let/const:

Scopes can be nested. When a variable is accessed, the JavaScript engine starts in the current scope and moves outward:

This example shows how each nested scope “shadows” variables from outer scopes. It’s one of those concepts that’ll feel intuitive once you’ve seen it in action a few times.
A common interview question demonstrates issues with scoping in loops:

The problem arises because var creates a single shared scope for the loop. By the time the returned function is called, the value of i has incremented to arr.length, and accessing arr[i] results in undefined. Here’s how to fix it:


Understanding scope is crucial for mastering JavaScript. Whether you’re preparing for interviews or building real-world projects, knowing how scope works will save you from countless bugs and help you write cleaner code. I can’t count how many times understanding these fundamentals has helped me debug a tricky issue.


Explore CS Prep further in our beginner-friendly program.
Get more free resources and access to coding events every 2 weeks.

Connect with one of our graduates/recruiters.

Our graduates/recruiters work at:

Connect with one of our recruiters to learn about their journeys.
Our graduates/recruiters work at: