3

In an interview, I was asked to guess the output of the following snippet:

var foo = 1;
    
function bar() {
    foo = 10;
    return;
    function foo() {
    }
}

bar();

console.log(foo);

and I thought the output will be 10 because the bar function returns right after reassigning the value of foo but the actual output is 1. Is it because of the function definition with the same variable name(foo)? Is a new scope created for the foo variable inside bar?

Ramesh Reddy
  • 10,159
  • 3
  • 17
  • 32
  • because `foo` in `bar()` is defined function, not variable from parent scope – tarkh Aug 14 '20 at 12:23
  • `foo` as the name of the local function is hoisted and overrides the `var foo` in the higher scope – Alex K. Aug 14 '20 at 12:23
  • You are right. You've redefined `foo` in local scope of function. As long as there is any definition inside of function scope - the global one won't be affected. – Jax-p Aug 14 '20 at 12:23
  • The output could be `10`. Cant say for certain by just *seeing* the code. `"fоo" === "foo"` – Lain Aug 14 '20 at 15:35

2 Answers2

5

That's a nasty (and somewhat pointless) question to ask in an interview!

It is indeed got to do with the function foo in the scope of bar - without that it does what you would have expected.

 var foo = 1;
    
function bar() {
    foo = 10;
    return;
    
}

bar();

console.log(foo);

The reason is due to "hoisting" - the function declaration within bar gets hoisted to the start of the function bar as a new variable, and due to the nature of javascript letting you change the type at runtime, it allows you to set it (and not the global) foo to 10.

It is essentially the same as this code:

 var foo = 1;
    
function bar() {
    var foo;
    foo = 10;
}

bar();

console.log(foo);
Jamiec
  • 133,658
  • 13
  • 134
  • 193
3

The function declaration inside bar creates a new local name foo, which shadows the outer one. Essentially the function foo() {} line is hoisted to the top of the function. You can see this here:

function bar() {
    console.log(foo);
    foo = 10;
    console.log(foo);
    return;
    function foo() {}
}

bar();

So foo = 10 modifies the local foo name, not the global one.

deceze
  • 510,633
  • 85
  • 743
  • 889