1

Context

I have this code

var a = 10;
 
// function "outer" created a closure of the global scope
// the moment it was defined
function outer() {
    // variable a is available in this scope (execution context)
    const b = 10;
 
    // function "inner" created a closure of the global scope
    // and outer function's scope the moment it was defined.
    // When it's executed it can use this closure as part of
    // its own scope
    function inner() {
        // variables a and b are available in this scope
        const c = 20;
        console.log(a + b + c);
    }
 
    return inner;
}

The closure for inner has these scopes:

  • Local scope
  • Outer function's scope
  • Global scope

Let's execute outer and then execute the return value, which is inner :

const inner = outer();
inner() // prints 40

Now here is where I am confused. I always thought that the inner function gets a "snapshot" of variables a and b as they existed the moment inner was defined.

So, I thought that after const inner = outer();, then every execution of inner would always return 40.

However I came to find out (while making a demonstration nonetheless) that this is not what happens

const inner = outer();
a = 100;
inner() // prints 130 while I expected for inner to be "locked" to 40

Question

I would like someone to clarify/correct my mental model of how closures work in js.

More specifically, I expected that the moment a function is defined, it gets a hold of all the outer scopes defined up to that moment and var (or const or let) values stay "locked" to the values they had the moment the function (in this case function inner) was defined.

However, I just showcased that altering the value of one of the variables referenced inside inner actually changes its return value.

So, values are evaluated "live" when the inner function gets executed instead of being a snapshot of what they were the moment inner was defined?

Dimitris Karagiannis
  • 8,942
  • 8
  • 38
  • 63
  • 1
    Java behaves as you describe (well, before arrow functions), but not JavaScript. The closure is a live place where those variables "live", and they can be changed. – Pointy Jan 22 '21 at 20:21
  • 1
    A closure remembers the connection between the variable and a location where its value is stored. That location can be updated, which is what happens when you reassign the variable. – Barmar Jan 22 '21 at 20:26
  • 1
    Your mental model should consider references rather than variables. That should clear things up. – Randy Casburn Jan 22 '21 at 20:27
  • 1
    [This "better programing" article](https://medium.com/better-programming/execution-context-lexical-environment-and-closures-in-javascript-b57c979341a5) will probably tell you more than you ever wanted to know about this issue. – Cat Jan 22 '21 at 20:30
  • 1
    @RandyCasburn of course, almost everything works by reference in JS, it makes total sense in hindsight. Thanks. – Dimitris Karagiannis Jan 22 '21 at 20:34

0 Answers0