Leaderboard
Javascript Jul 8, 2026
Javascript Closure Captures By Reference Not Value

JavaScript Closures — What is the Output?

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Closure Captures By Reference Not Value and improve your technical interview readiness.

let x = 1
const add = () => x + 1
x = 10
console.log(add())
A 2
B 11
C 1
D ReferenceError

Detailed Explanation

Why This Question Matters

If you've spent any time in a technical interview or a JavaScript deep-dive, you've probably run into questions that look deceptively simple but are designed to trip you up. This specific snippet is a classic. It tests whether you actually understand how JavaScript handles variables and functions, or if you're just guessing based on how other languages work.

The core concept here is closures and lexical scoping. A lot of developers assume that a function "captures" the value of a variable at the moment the function is defined. If that were true, the answer to this puzzle would be 2. But JavaScript doesn't work that way. Understanding this distinction is the difference between writing predictable code and spending four hours debugging a weird state bug in a React component.

Understanding the Code

Let's look at the snippet again:

let x = 1
const add = () => x + 1
x = 10
console.log(add())

At first glance, it's just a few lines. But here is what's actually happening under the hood.

First, we declare x using let and assign it 1. Then, we define a function called add. Now, pay close attention: the add function doesn't take any arguments, and it doesn't have its own local variable x. Instead, it looks "outside" itself to find x. This is called looking up the scope chain.

The key detail is that add doesn't store the *value* 1 inside itself. It stores a *reference* to the variable x in the surrounding environment.

When we hit x = 10, we aren't creating a new variable; we are updating the value of the existing x in memory. Finally, when we call add(), the function reaches out, sees that x is now 10, adds 1 to it, and returns 11.

Finding the Correct Answer

The correct answer is 11 (Option B).

Why not 2? Because add is a closure. A closure is essentially a function bundled together with its lexical environment. In plain English: the function remembers where it was born and has access to the variables that were available in that spot, regardless of when the function is actually executed.

If the code had been written like this:

let x = 1
const add = () => {
const internalX = x;
return internalX + 1;
}
// ... (some logic here)

Even then, if internalX was assigned *inside* the function body, it would still fetch the current value of x at the moment of execution. To get 2, you would have had to pass x as an argument to a function that froze the value, or used a pattern that captured the value at a specific point in time.

Common Mistakes Developers Make

The most common mistake is confusing pass-by-value with lexical referencing.

Beginners often think of functions as snapshots. They assume that when const add = () => x + 1 is written, the engine says, "Okay, x is 1, so this function is basically () => 1 + 1." That's not how JavaScript works. The function remains linked to the variable x.

Another trip-up happens when developers move into asynchronous code. Imagine if x = 10 happened inside a setTimeout or an await block. If you're not careful with how you scope your variables (using var vs let in old loops, for example), you can end up with "stale closures" where the function refers to a version of a variable you didn't expect.

Real-World Usage

You might be thinking, "Who actually writes code like this?" The answer is: you do, every day, if you use modern frameworks.

Take React hooks as a prime example. If you've ever struggled with useEffect or useCallback, you've fought with closures. When you define a function inside a component, that function captures the props and state of that specific render. If you don't include a variable in your dependency array, the function might be "closing over" an old value of a variable from a previous render, leading to the dreaded "stale state" bug.

This also applies to middleware in Express or higher-order functions in functional programming. Whenever you return a function from another function, you're creating a closure. Being able to predict exactly which variable the inner function is pointing to is critical for managing state in large-scale applications.

Key Takeaways

- Functions are not snapshots. They don't copy values; they maintain a reference to the environment where they were created.
- Lexical scoping means the function looks at where it was defined in the source code to determine which variables it has access to.
- Closures allow functions to "remember" and access variables from their parent scope even after the parent scope has finished executing.
- When you update a variable via let or var, any closure pointing to that variable will see the updated value the next time it is called.

Why this matters

Understanding Closure Captures By Reference Not Value is crucial for passing technical interviews. In real-world applications, this concept often leads to subtle bugs if not handled correctly. For more details, you can always refer to the official MDN Documentation.

📝
Reviewed by CodeShot Editorial
Every challenge is code-reviewed by senior developers to ensure accuracy and real-world relevance. Learn more.

Ready for your shot?

Join thousands of developers solving one logic puzzle every morning.

Solve Today's Challenge →