Original: Read on Medium This is a migrated version of the Medium post for this blog.
Closures and Scope Are Related, but Not the Same
Introduction
When developing with JavaScript, you frequently encounter the terms closure and scope. They are both core concepts, and understanding them clearly can improve code readability and performance.
In this post, we will look at the differences between scope and closure in detail, with practical examples. We will cover patterns such as private state with closures, this binding, and recursive closure behavior.
What Are Scope and Closure?
Scope is the region of code where a variable is defined and accessible. In JavaScript, scope is determined by where a variable is declared.
- Global scope: Variables declared outside functions or blocks can be accessed anywhere.
- Local scope: Variables declared inside functions or blocks are only accessible there.
Closure, on the other hand, is a function that can access both its own scope and its parent function's scope. A closure is created when a function is defined inside another function, and it can still "remember" outer variables even after the outer function returns.
The following code demonstrates this clearly:

In this example, inner is a closure because it can still remember and access x after outer has returned.
In short: scope defines where variables are accessible, while closures allow a function to retain access to variables from its creation environment.
Closure Examples
1. Returning a closure that returns an argument from the outer function
Example:
function outer(arg) {
return function inner() {
return arg;
};
}outer receives arg and returns a new function inner. Through closure, inner can access and return arg.
const getArg = outer('hello');
console.log(getArg()); // prints 'hello'Even after outer has returned, inner can still access arg.
2. Creating private variables with closures
Closures are a common way to build private variables in JavaScript through scope and encapsulation.

In this pattern, Counter returns an object with methods such as increment and getCount, while privateCount remains inaccessible outside the function scope.
This is a standard encapsulation approach in JavaScript for private-like state management.
3. How closures interact with this
this refers to the current execution context of a function. It can point to different objects depending on how the function is called.
When a closure is created, it captures lexical scope, and this behavior still depends on invocation context unless explicitly bound.
Closure and this interaction example:

Execution points:
outersetsthis.nameto'outer'.inneris created as a closure insideouter.- When
innerFuncis called,thisrefers to the object passed tocall(), such as { name: 'newContext' }. - Even though
innerwas created in another context, the invocation context controls the currentthisunless it is lexically bound (for example, with arrow functions).
Key points:
- Closures preserve lexical variables from their creation scope.
thisis not automatically preserved in the same way as lexical variables.- Use
bind(),call(), orapply()when explicitthisbinding is required.
4. Returning a closure that logs call count
Here is an example that logs how many times a wrapped function is called:

How it works:
logCallCountreceives a functionfn.- It initializes
callCountto0. - It returns a wrapper function.
- Each wrapper invocation increments
callCountand logs it. - The original function is called via
apply()to preserve context and arguments.
Usage example:
const loggedAdd = logCallCount(function add(a, b) {
return a + b;
});
console.log(loggedAdd(1, 2)); // logs call count, then returns 3
console.log(loggedAdd(3, 4)); // logs call count, then returns 7
loggedAddwraps the originaladdfunction. Every call logs invocation count and returns the original result.
5. Closures in recursive functions
Closures in recursive functions work similarly to non-recursive closures. The important difference is that recursive calls create new scopes repeatedly, and closures can access state across those calls.

How it works:
recursiveClosureis called, setsx, initializescount, definesinner, and returns it.inneraccesses variables fromrecursiveClosurethrough closure.recursiveFuncstores the returnedinner.- Calling
recursiveFunc(3)executesinner, incrementscount, and logs state. innerrecursively calls itself while decrementingy.- Recursion ends when
yreaches0.
Final output sequence:
- First call:
Call 1: x = 5, y = 3 - Second call:
Call 2: x = 5, y = 2 - Third call:
Call 3: x = 5, y = 1 - Fourth call:
Call 4: x = 5, y = 0