Leaderboard
Javascript Apr 15, 2026
Javascript Hoisting Function Scope

JavaScript Closures - What gets logged in a closure?

This is a daily Javascript challenge from the CodeShot archive. Practice your knowledge of Hoisting Function Scope and improve your technical interview readiness.

function foo() {
  console.log(a)
  var a = 10
}
foo()
A 10
B ReferenceError
C undefined
D null

Detailed Explanation

Why This Question Matters

If you’ve ever stared at a undefined value in your console and wondered, "But I defined that variable right there!", you've run into hoisting.

It's one of those JavaScript quirks that feels like a bug until you understand how the engine actually reads your code. For senior developers, this is a trivial concept, but it's a classic interview trap because it tests whether you actually understand the execution context or if you're just guessing based on how other languages work.

Most people assume code executes strictly from top to bottom. In reality, JavaScript does a bit of "pre-scanning" before a single line of logic actually runs.

Understanding the Code

Let's look at the snippet again:

function foo() {
  console.log(a)
  var a = 10
}
foo()

At first glance, it looks like we're trying to print a before we assign it the value 10. You might expect a ReferenceError because a hasn't been declared yet. But that's not what happens.

Here is what's happening under the hood. When the JavaScript engine enters the foo() function, it creates an execution context. Before executing the code, it scans for variable declarations.

When it sees var a = 10, the engine splits that line into two distinct steps:
1. Declaration: var a; (This is hoisted to the top of the function scope).
2. Assignment: a = 10; (This stays exactly where you wrote it).

So, to the JS engine, your code actually looks like this:

function foo() {
  var a;          // Declaration is hoisted, initialized as undefined
  console.log(a)  // Logs the current value of a
  a = 10          // Assignment happens here
}

Finding the Correct Answer

The correct answer is Option C: undefined.

Here is why the other options are wrong:

  • 10: This would only happen if the assignment was also hoisted, but only the *declaration* moves. The value stays put.
  • ReferenceError: You'd get this if a didn't exist at all, or if you used let or const. Since var is used, the variable exists in the scope from the moment the function starts.
  • Null: JavaScript never automatically initializes variables to null. It's always undefined until you explicitly give it a value.
  • Common Mistakes Developers Make

    The biggest trap here is assuming var behaves like let or const.

    If we swap var for let, the result changes completely:

    function foo() {
      console.log(a) // ReferenceError: Cannot access 'a' before initialization
      let a = 10
    }
    

    With let and const, the variable is still "hoisted" in a technical sense, but it enters what we call the Temporal Dead Zone (TDZ). The engine knows the variable exists, but it forbids you from touching it until the code execution actually reaches the line where it's declared.

    Beginners often confuse "hoisting" with "automatic initialization." Hoisting just means the declaration is moved; it doesn't mean the value moves with it.

    Real-World Usage

    In a modern production environment, you'll rarely see var because we've moved to ES6+ standards. However, understanding this is still crucial for a few reasons:

    1. Legacy Codebases: You will inevitably encounter old JS files in a corporate codebase. If you don't understand hoisting, you'll spend hours debugging why a variable is undefined instead of throwing an error.
    2. Function Hoisting: While variable hoisting is annoying, function hoisting is actually useful. You can call a function at the top of your file even if it's defined at the bottom. This allows you to put your high-level logic at the top and hide the implementation details (the helper functions) further down.
    3. Debugging Scope: Understanding execution contexts helps you debug closure issues and memory leaks. When you know how the engine allocates space for variables before running the code, you can better predict how your application will behave under different conditions.

    Key Takeaways

  • var declarations are hoisted and initialized as undefined.
  • Assignments are not hoisted; they happen exactly where they are written.
  • let and const are also hoisted, but they stay in the Temporal Dead Zone, meaning accessing them early triggers a ReferenceError.
  • To avoid these headaches, stick to const by default, use let when you need to reassign, and basically forget that var exists unless you're maintaining a project from 2014.
  • Why this matters

    Understanding Hoisting Function Scope 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 →