DEV Community

ValPetal Tech Labs
ValPetal Tech Labs

Posted on

Javascript Question of the Day #14 [Talk::Overflow]

This post explains a quiz originally shared as a LinkedIn poll.

🔹 The Question

var x = 10;
function x() { return 20; }
console.log(typeof x);
console.log(x);
Enter fullscreen mode Exit fullscreen mode

Hint: When a variable and a function share the same name in the same scope, only one binding is created. Think about what gets hoisted and which initializer runs last.


🔹 Solution

Output:

number
10
Enter fullscreen mode Exit fullscreen mode

So the correct answer is B) number, then 10.

🧠 How this works

In JavaScript, hoisting moves declarations to the top of their scope at compile time. For the same scope, only one binding is created when both a var and a function declaration use the same name. The spec says that the function declaration wins for the initial value of that binding. So at the start of the scope, x is the function. Then the code runs in order: the assignment x = 10 runs (overwriting the function), so by the time of the console.log calls, x is the number 10.

The platform behaves this way because:

  1. Creation phase: The engine creates one binding for x, and the function declaration initializes it to the function object.
  2. Execution phase: var x = 10 does not declare a second binding; it only assigns. So x = 10 runs and overwrites the function.
  3. typeof x is "number" and x is 10.

In real code, this often shows up when someone adds a variable with the same name as an existing function (e.g. after a refactor or in a merged branch), leading to the function being replaced by a number or other value and breaking calls like x().

🔍 Line-by-line explanation

  1. Creation phase (before any line runs):

    • var x and function x() { return 20; } are hoisted.
    • One binding x exists. Function declarations win, so x is initially the function.
  2. Execution:

    • var x = 10 — no new binding; the assignment runs and sets x to 10.
    • function x() { ... } — already processed in creation; no effect here.
    • console.log(typeof x)x is 10, so logs "number".
    • console.log(x) — logs 10.

The non-obvious part is that both the var and the function declaration contribute to the same binding, and the function wins for the initial value, but the first assignment that runs (x = 10) then overwrites it.


🔹 Key Takeaways

  1. In the same scope, one name can be declared with both var and a function declaration; only one binding is created, and the function declaration wins for the initial value.
  2. Assignments run in execution order and overwrite that binding; they do not create a second variable.
  3. Hoisting applies to declarations (and their initial values for functions), not to assignments; var x = 10 hoists the declaration but the assignment runs when the line executes.
  4. To avoid this class of bugs, avoid reusing the same identifier for a variable and a function in the same scope; use distinct names or block scope (let/const) so the intent is clear.
  5. "Duplicate" declarations with the same name in one scope are allowed for var and function declarations; the engine does not throw, but the runtime behavior (one binding, overwritten by assignment) can be surprising.

Top comments (0)