
Now, before we start running secure booking function down here,
our code is running in the global execution context.

Then when secure booking is actually executed, a new execution context is put on top of the execution stack.

Now, remember, each execution context has a variable environment,
which contains all its local variables.
In this case, it only contains the passengerCount set to zero.
This variable environment is also the scope of this function.
And so the scope chain of this execution context looks like this(오른쪽 상단 securebooking() scope).
So passengerCount is in the local scope, but of course this scope also gets access to all variables of the parent's scopes.
And in this case, just a global scope.

Anyway, in the next line of the secure booking function, a new function is returned and it will be stored in the Booker able.
So the global context now also contains the Booker variable.
(booker 오른쪽추가됨)
--
And now what else happens whenthe secure booking function returns?

Well, that's right.
Its execution context pops off the stack and disappears.
So the secure booking function has done its job and has now finished execution.


then how is this even possible?
How can the Booker function update this passengerCount variable that's defined in a secure booking function that actually has already finished executing.
And so, as I just said,
this function has already finished its execution.
It is gone.
So its execution context is no longer on the stack, as we just saw in the slide,
but still this inner function here, which is the Booker function, is still able to access the passengerCount variable that's inside of the Booker function that should no longer exist.
So again, this Booker function here is simply a function that exists out here in the global environment or in the global scope, right?
And the environment in which the function was created.
So this year basically, this environment is no longer active.
It is in fact gone.
But still the Booker function somehow continues to have access to the variables that were present at the time that the function was created.
And in particular, this passengerCount variable here(let passengerCount = 0).
And so that's exactly what the closure does.
So we can say that a closure makes a function remember all the variables that existed at the function's birthplace essentially, right?

So we can imagine the secure booking as being the birthplace of this function.
So of the Booker function, essentially.
And so this function remembers everything at its birthplace, by the time it was created.
And this cannot simply be explained with the scope chain alone.
So we need to also understand the closure.

And note that Booker is really this function here, located in the global scope.
Anyway, the first thing that's gonna happen is that a new execution context is created
and put on top of the call stack
and the variable environment of this context is emptied
simply because there are no variables declared in this function.

Now what about the scope chain?
Well, since Booker is in the global context, it's simply a child's scope of the global scope,
just like this, but maybe now you're starting to see the problem.
So how will the Booker function access the passengerCount variable?
It's nowhere to be found in the scope chain, right?
So this is where we start to unveil the secret of the closure

Any function always has access to the variable environment of the execution context in which the function was created.
Now, in the case of Booker, this function was created.
It was born in the execution context of secure booking, which was popped off the stack previously, remember?

So, therefore the Booker function will get access to this variable environment, which contains the passengerCount variable.
And this is how the function will be able to read and manipulate the passengerCount variable.
And so it's this connection that we call closure.
So let's say all that again, to make this really clear.
So a function always has access to the variable environment(VE) of the execution context in which it was created, even after a debt execution context is gone.
And this last part is really important.
The closure is then basically this variable environment attached to the function,exactly as it was at the time and place that the function was created.
And this probably still sounds confusing, but don't worry.
I have some more familiar analogies in the next slide.
So what matters the most here is that the Booker function has access to the passengerCount variable because it's basically defined in the scope
in which the Booker function was actually created.
So in a sense, the scope chain is actually preserved through the closure, even when a scope has already been destroyed
because its execution context is gone.
This means that even though the execution context has actually been destroyed,
the variable environment somehow keeps living somewhere in the engine.

Now we can say that the Booker function closed over its parents scope or over its parent variable environment.
And this includes all function arguments.
Even though in this example, we don't have any.
And now this attached or closed over variable environment stays with the function forever.
It will carry it around and be able to use it forever.
To make it a bit more digestible,
we can also say that thanks to the closure, a function does not lose connection to variables that existed at the function's birthplace.
That's a bit more intuitive, right?

But anyway, let's see what happens now with execution of the Booker function.
So the function attempts to increasethe passengerCount variable.
However, this variable is not in the current scope.
And so JavaScript will immediately look into the closure
and see if it can find the variable there.
And it does this even before looking at the scope chain.
For example, if there was a global passengerCount variable set to 10,
it would still first use the one in the closure.
So the closure basically has priority over the scope chain.
And so after running this function, the passengerCount becomes one.
This message is logged. And then the execution context is popped off the stack.

Then execution moves to the next line.
We get a new execution context and a closure is still there, still attached to the function and the value is still one.
And so now this function executes, increasing the passengerCount to 2 and logging a message again.



And so then as we reassign the function to a new value,
then that old closure basically disappears
and now the closure is b.

So this variable here of the birthplace where it was reassigned.
And this is really fascinating in my opinion that the closure can change like this as the variable is reassigned.
So it really is true that a closure always makes sure that a function does not lose the connection to the variables that were present at its birthplace.
In our case here, the function was kind of born inside of g first
and then it was essentially reborn again in h.

