Closures | JavaScript 🔥 | Lecture 128

The Coding Classroom
29 Apr 202319:48

Summary

TLDRThis video script delves into the intricate world of closures in JavaScript, a concept often deemed challenging yet deeply powerful. The instructor methodically demystifies closures, guiding learners through their inner workings using relatable analogies and practical examples. By linking closures to familiar notions like execution contexts, scope chains, and variable environments, the video unveils the seamless interplay that allows functions to retain access to variables from their birthplaces, even after those environments have ceased to exist. With its comprehensive explanations, code walkthroughs, and insightful definitions, this script illuminates a pivotal JavaScript feature, empowering developers to harness its capabilities confidently.

Takeaways

  • 🔑 Closures are an automatic mechanism in JavaScript where a function remembers the variables from the environment in which it was created, even after that environment is gone.
  • 🧩 Closures allow functions to access and manipulate variables from their parent's scope, even after the parent function has finished executing.
  • 🕰️ Closures preserve the scope chain and variable environment of a function, even when the execution context in which the function was created is no longer on the call stack.
  • 🎁 A closure is like a function carrying a 'backpack' containing all the variables that existed at the function's birthplace, which it can access anytime.
  • 🌍 Closures ensure that a function never loses its connection to the variables from its 'hometown' (parent scope), even after its parent scope is gone.
  • 🔎 Closures are not something we create manually; JavaScript handles them automatically when functions are created within other functions.
  • 🚫 We cannot directly access or manipulate the closed-over variables in a closure, but we can observe the closure's effects.
  • 🧠 Understanding closures requires a solid grasp of execution contexts, the call stack, and the scope chain.
  • 🔗 Closures bring together concepts like execution contexts, call stacks, and scope chains in a beautiful and powerful way.
  • 🚀 Mastering closures is crucial for becoming a confident and proficient JavaScript programmer.

Q & A

  • What is a closure in JavaScript?

    -A closure in JavaScript is a feature where an inner function has access to the variables of its outer (enclosing) function's scope, even after the outer function has executed and its execution context is no longer on the call stack.

  • How are closures created in JavaScript?

    -Closures are created automatically in certain situations when an inner function is defined within an outer function. This happens without the need for explicit actions by developers, like manually creating closures.

  • Why is the concept of closures considered difficult to understand by many developers?

    -Many developers find closures difficult to understand because they involve several JavaScript concepts like execution context, call stack, and scope chain, working together in a complex way.

  • What is the 'secure booking' function's role in demonstrating closures?

    -The 'secure booking' function demonstrates closures by encapsulating a 'passengerCount' variable and returning an inner function that modifies this variable, showcasing how the inner function retains access to the outer function's variables even after the outer function has executed.

  • Can closures be manually created like objects or arrays?

    -No, closures are not created manually like objects or arrays. They occur automatically in certain situations when functions are created and executed.

  • How does the 'Booker' function illustrate the concept of closures?

    -The 'Booker' function, returned from 'secure booking', illustrates closures by accessing and modifying the 'passengerCount' variable of its parent function, demonstrating how inner functions retain access to the variables of their outer functions.

  • Why can the 'Booker' function still access the 'passengerCount' variable after the 'secure booking' function has finished executing?

    -The 'Booker' function can still access the 'passengerCount' variable due to closures, which allow functions to remember and access the variables from their birthplace's scope, even after that scope's execution context is gone.

  • What is the significance of the variable environment in closures?

    -The variable environment in closures is significant because it contains all the local variables of a function's execution context. It is attached to the inner function, allowing it to access and manipulate these variables even after the outer function's execution context has been popped off the call stack.

  • How does the concept of closures alter the traditional understanding of the scope chain?

    -Closures extend the traditional understanding of the scope chain by preserving the scope chain through the closure, even after a function's execution context has been destroyed, allowing inner functions to access variables from their enclosing functions' scopes.

  • How can developers observe closures in action within their code?

    -Developers can observe closures in action by using `console.dir` to inspect functions in the console. This method allows them to see the 'scopes' internal property, where the closure's variable environment, including accessible variables like 'passengerCount', is displayed.

Outlines

00:00

🚪 Understanding Closures: The Mystical Feature of JavaScript Functions

This paragraph introduces the concept of closures in JavaScript functions, which many developers find challenging to understand. It emphasizes that with the right explanation and an understanding of concepts like execution context, call stack, and scope chain, closures become less complicated. The paragraph sets up an example to demonstrate how closures work, where a function called 'secureBooking' is created to manipulate a 'passengerCount' variable. This function returns another function, which can access and update the 'passengerCount' variable even after the 'secureBooking' function has finished executing. The paragraph ends by explaining that this is possible because of closures, which allow functions to remember variables from their birthplace.

05:04

🔑 Unveiling the Closure: How the 'Booker' Function Accesses 'passengerCount'

This paragraph continues the example from the previous paragraph, analyzing how the 'Booker' function, created by the 'secureBooking' function, can access and update the 'passengerCount' variable. It demonstrates that calling the 'Booker' function multiple times increments the 'passengerCount' variable, even though the 'secureBooking' function has finished executing. The paragraph highlights the seemingly strange behavior of the 'Booker' function being able to access a variable from a function that no longer exists in the execution context. It sets the stage for explaining how closures make this possible.

10:04

🧩 The Mechanism Behind Closures: Preserving Variable Environments

This paragraph dives deeper into the mechanism behind closures, explaining that a function always has access to the variable environment of the execution context in which it was created, even after that execution context is gone. It uses the example of the 'Booker' function, which was created in the execution context of 'secureBooking', and therefore has access to the 'passengerCount' variable through the closure. The paragraph provides multiple definitions and analogies to help understand closures, such as a function preserving the scope chain throughout time, not losing connection to its birthplace, and carrying a backpack of variables from its creation environment.

15:04

🔍 Exploring Closures: Examples, Accessing Closed Variables, and Importance

This paragraph clarifies that closures are created automatically by JavaScript, and developers do not need to create them manually. It also mentions that closed-over variables cannot be accessed directly, as closures are an internal property of a function. The paragraph demonstrates how to inspect the closure using 'console.dir' to view the internal scope property containing the closed-over variables. It emphasizes the importance of understanding closures, as they are frequently used in JavaScript, often without developers realizing it. The paragraph concludes by stating that understanding closures is crucial for becoming a confident programmer, as it is essential to know how everything in the code works.

Mindmap

Keywords

💡Closure

A closure is a fundamental concept in JavaScript that allows a function to access and remember variables from its outer (enclosing) function, even after the outer function has finished executing. It is the mechanism by which a function maintains a reference to variables from an execution context that should have been destroyed. The video emphasizes the 'magical' nature of closures, where functions can manipulate variables that seem to no longer exist.

💡Execution Context

An execution context is an abstract concept in JavaScript that tracks the execution of code. It consists of a variable environment (variables and their values) and the scope chain (references to outer variable environments). Execution contexts are created when code is executed and are stacked on the call stack, with the current context being on top. Understanding execution contexts is crucial for grasping how closures work, as closures 'preserve' the variable environment even after the execution context is gone.

💡Call Stack

The call stack is a data structure that keeps track of the execution contexts created during the execution of a JavaScript program. When a function is called, its execution context is pushed onto the call stack. When the function completes, its execution context is popped off the stack. The video uses the call stack to illustrate how closures can access variables from execution contexts that have already been removed from the stack.

💡Scope Chain

The scope chain is a series of variable environments that are accessible to a particular execution context. It starts with the variable environment of the current execution context and includes the outer (parent) environments as well. The scope chain determines where variables can be accessed and found. However, the video explains that closures allow functions to access variables outside of the normal scope chain, even after the execution context has been destroyed.

💡Variable Environment

The variable environment is a component of an execution context that stores variables and their values for that specific context. It is essentially the scope in which variables are defined and can be accessed. The video highlights that closures allow functions to retain access to the variable environment of their parent function, even after the parent function has returned and its execution context is gone.

💡Birthplace

In the context of closures, the 'birthplace' refers to the execution context in which a function was created. The video uses analogies like a person's hometown or a backpack to illustrate how a function 'remembers' the variables that existed at its birthplace (the parent function's execution context) through the closure mechanism, even after the birthplace no longer exists.

💡Lexical Environment

The lexical environment is the context in which a function was written, and it determines the scope chain and variable environment for that function. Closures are a characteristic of the lexical environment, as they allow a function to access variables from its outer (enclosing) lexical environment, even after that environment no longer exists.

💡Scope

Scope refers to the visibility and accessibility of variables in a JavaScript program. It determines where a variable can be accessed and used. The video discusses how closures enable functions to access variables outside of their normal scope, by retaining a reference to the variable environment of their parent function, even after that parent function's scope has been destroyed.

💡Global Scope

The global scope is the outermost scope in a JavaScript program, and it is accessible from anywhere in the code. Variables and functions defined in the global scope are globally accessible. The video uses the global scope as a reference point when discussing how closures allow functions to access variables from their parent function's scope, even after that parent scope has been destroyed.

💡Higher-Order Functions

Higher-order functions are functions that can take other functions as arguments or return functions as their output. The video illustrates closures by using an example where a function returns another function, which then has access to variables from the outer function's scope, even after the outer function has completed execution. Higher-order functions are closely related to the concept of closures in JavaScript.

Highlights

A closure makes a function remember all the variables that existed at the function's birthplace essentially, right?

A function always has access to the variable environment of the execution context in which it was created, even after that execution context is gone.

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.

A function does not lose connection to variables that existed at the function's birthplace.

Thanks to the closure, a function does not lose connection to variables that existed at the function's birthplace.

A closure gives a function access to all the variables of its parent function, even after that parent function has returned.

A closure makes sure that a function does never lose connection to the variables that existed at the function's birthplace.

A function has a backpack, which it carries around wherever it goes. And this backpack contains all the variables that were present in the environment in which the function was created.

We do not have to create closures manually. This is something that JavaScript does completely automatically.

There is no way for us to explicitly access closed over variables.

Closures are an internal property of a function.

We cannot directly access these variables, but we can observe that a closure happens because functions magically keep having access to variables that should no longer exist.

Closures are a feature that's used all the time in JavaScript, and many times, even without us realizing that closures are happening.

To become a confident programmer, you need to know how exactly everything in your code works, including closures.

A closure is not a feature that we explicitly use. We don't create closures manually, like we create a new array or a new function. A closure simply happens automatically in certain situations, we just need to recognize those situations.

Transcripts

play00:01

There is an almost mystical feature

play00:03

of Java script functions

play00:05

that many developers fail to fully understand.

play00:09

And what I'm talking about is something called closures.

play00:13

So when I asked my students,

play00:15

what's the hardest JavaScript concept to understand,

play00:18

then many people say that it's closures.

play00:22

However, I believe that with the right explanation,

play00:25

it's actually not that hard,

play00:27

especially when you already understood everything

play00:30

that you learned before in this course,

play00:33

such as execution context,

play00:35

the call stack, and the sculpt chain,

play00:37

because closures kind of bring all of these concepts

play00:40

together in a beautiful, almost magical way.

play00:45

So enough talk, let's see what closures are all about.

play00:51

So I'm gonna start by creating a new function here

play00:54

called secure booking.

play01:00

And it is this function that will create the closure.

play01:04

Now, the first thing that I need to tell you about closures

play01:08

is that a closure is not a feature that we explicitly use.

play01:13

So we don't create closures manually,

play01:16

like we create a new array or a new function.

play01:20

So a closure simply happens automatically

play01:22

in certain situations, we just need

play01:25

to recognize those situations.

play01:28

And so that's what we're gonna do here in this example.

play01:31

So we will create one of those situations

play01:33

so that we can then take a look at a closure.

play01:38

So anyway, let's now continue writing this example

play01:43

and I'm calling this one passengerCount

play01:46

and it will start at zero, but we will be

play01:49

able to manipulate it.

play01:51

And I'm calling this function here,

play01:53

secure booking because this passengerCount variable

play01:55

cannot be manipulated and accessed from the outside.

play02:02

So, and now what's special about this function

play02:05

is that it will return a new function.

play02:12

And what we do in this function is to update

play02:15

the passengerCount variable.

play02:19

So the variable that is defined in the parent function.

play02:23

So that's important.

play02:25

And then let's just log the new passengerCount

play02:28

to the console.

play02:32

So passengerCount, alright,

play02:37

and now let's call the secure booking function

play02:41

and then store the result in a variable called Booker.

play02:46

And so this is actually pretty similar to what we did

play02:49

previously in the lecture of functions

play02:52

returning other functions.

play02:54

So we have one function here that we call

play02:56

and this function will return this new function.

play03:00

And so as we call secure booking,

play03:02

it will return exactly this function

play03:05

and it will then be stored inside this Booker.

play03:09

And so this here is gonna be now a function as well, right?

play03:13

So let's analyze in detail

play03:15

what happens when this line of code here

play03:17

is executed using all the concepts

play03:20

that we already know about.

play03:23

So this is exactly the code that we just wrote.

play03:26

Now, before we start running

play03:28

the secure booking function down here,

play03:30

our code is running in the global execution context.

play03:34

And in there, we currently only have

play03:36

this secure booking function.

play03:39

And so we can also say that the global scope

play03:42

now contains secure booking.

play03:44

Then when secure booking is actually executed,

play03:48

a new execution context is put

play03:50

on top of the execution stack.

play03:53

Now, remember, each execution context

play03:56

has a variable environment,

play03:58

which contains all its local variables.

play04:01

In this case, it only contains the passengerCount

play04:04

set to zero.

play04:07

This variable environment is also

play04:09

the scope of this function.

play04:11

And so the scope chain of this execution context

play04:14

looks like this.

play04:16

So passengerCount is in the local scope,

play04:19

but of course this scope also gets access

play04:22

to all variables of the parent's scopes.

play04:25

And in this case, just a global scope.

play04:28

Anyway, in the next line of the secure booking function,

play04:32

a new function is returned and it will be stored

play04:36

in the Booker variable.

play04:37

So the global context now also contains the Booker variable.

play04:42

And now what else happens when

play04:44

the secure booking function returns?

play04:47

Well, that's right.

play04:48

Its execution context pops off the stack and disappears.

play04:53

So the secure booking function has done its job

play04:56

and has now finished execution.

play04:59

It really is gone now and that's important to be aware of

play05:03

and to keep in mind.

play05:05

And for now, that's actually all we did.

play05:08

So all this is nothing new at this point, right?

play05:11

All we did was to analyze the call stack

play05:14

and the scope chain as we call the secure booking function.

play05:18

And this is gonna be important to later on

play05:20

understand the closure.

play05:22

So as of yet, we didn't see the closure yet.

play05:26

All we did was use the knowledge that we already have

play05:29

to understand how this Booker function was created,

play05:33

because that's gonna be important for the next step.

play05:37

So let's now go back to our code

play05:39

to actually use the Booker function,

play05:42

and then finally see the closure in action.

play05:46

So now that we understand how the Booker function

play05:49

was created, let's now actually call it here.

play05:54

So calling it a couple of times here, and as we can see,

play05:58

it doesn't need any arguments.

play06:00

There's no list of parameters, right?

play06:05

So let's call it here three times

play06:09

and now let's reload the page here.

play06:13

And indeed we get one, two, three passengers.

play06:17

And so what this means is that the Booker function

play06:20

was in fact able to increment the passengerCount

play06:24

to one, then to two and then to three.

play06:28

But now if we think about this,

play06:30

then how is this even possible?

play06:33

How can the Booker function update

play06:35

this passengerCount variable that's defined

play06:38

in a secure booking function

play06:40

that actually has already finished executing.

play06:44

And so, as I just said,

play06:45

this function has already finished its execution.

play06:48

It is gone.

play06:50

So its execution context is no longer on the stack,

play06:53

as we just saw in the slide,

play06:56

but still this inner function here,

play06:59

which is the Booker function,

play07:01

is still able to access the passengerCount variable

play07:04

that's inside of the Booker function

play07:07

that should no longer exist.

play07:10

And maybe you can guess that what makes this possible

play07:13

is a closure, but before I explain

play07:17

exactly how the closure works,

play07:19

I want you to appreciate once more,

play07:21

how strange this actually is.

play07:24

So again, this Booker function here

play07:27

is simply a function that exists

play07:30

out here in the global environment

play07:32

or in the global scope, right?

play07:35

And the environment in which the function was created.

play07:38

So this year basically, this environment

play07:41

is no longer active.

play07:44

It is in fact gone.

play07:46

But still the Booker function somehow continues

play07:49

to have access to the variables

play07:50

that were present at the time that the function was created.

play07:55

And in particular, this passengerCount variable here.

play07:59

And so that's exactly what the closure does.

play08:02

So we can say that a closure makes a function

play08:05

remember all the variables that existed

play08:08

at the function's birthplace essentially, right?

play08:12

So we can imagine the secure booking

play08:15

as being the birthplace of this function.

play08:19

So of the Booker function, essentially.

play08:22

And so this function remembers everything at its birthplace,

play08:25

by the time it was created.

play08:28

And this cannot simply be explained

play08:31

with the scope chain alone.

play08:33

So we need to also understand the closure.

play08:35

And so let me now, really explain how it actually works.

play08:40

So this is how we left the call stack

play08:43

and the sculpt chain after the last slide.

play08:46

And the most important thing to notice here

play08:49

is that the execution context of secure booking

play08:52

is no longer on call stack,

play08:55

because again, this function has finished

play08:58

execution long ago.

play09:00

So now it's time to finally run the Booker function

play09:04

and see exactly what's gonna happen here.

play09:07

And note that Booker is really this function here,

play09:11

located in the global scope.

play09:14

Anyway, the first thing that's gonna happen

play09:17

is that a new execution context is created

play09:20

and put on top of the call stack

play09:23

and the variable environment of this context is emptied

play09:27

simply because there are no variables

play09:29

declared in this function.

play09:31

Now what about the scope chain?

play09:34

Well, since Booker is in the global context,

play09:37

it's simply a child's scope of the global scope,

play09:41

just like this, but maybe now

play09:44

you're starting to see the problem.

play09:46

So how will the Booker function access

play09:49

the passengerCount variable?

play09:52

It's nowhere to be found in the scope chain, right?

play09:56

So this is where we start to unveil

play09:58

the secret of the closure

play10:01

and the secret is basically this.

play10:04

Any function always has access to the variable environment

play10:07

of the execution context in which the function was created.

play10:13

Now, in the case of Booker, this function was created.

play10:16

It was born in the execution context of secure booking,

play10:22

which was popped off the stack previously, remember?

play10:26

So, therefore the Booker function

play10:28

will get access to this variable environment,

play10:32

which contains the passengerCount variable.

play10:35

And this is how the function will be able to read

play10:39

and manipulate the passengerCount variable.

play10:42

And so it's this connection that we call closure.

play10:47

So let's say all that again, to make this really clear.

play10:51

So a function always has access to the variable environment

play10:55

of the execution context in which it was created,

play10:59

even after a debt execution context is gone.

play11:03

And this last part is really important.

play11:06

The closure is then basically this variable environment

play11:10

attached to the function,

play11:12

exactly as it was at the time and place

play11:15

that the function was created.

play11:18

And this probably still sounds confusing, but don't worry.

play11:22

I have some more familiar analogies in the next slide.

play11:26

For now, we are just trying to understand the mechanism

play11:29

behind the closure, so how it all works behind the scenes.

play11:33

So what matters the most here is that the Booker function

play11:37

has access to the passengerCount variable

play11:40

because it's basically defined in the scope

play11:43

in which the Booker function was actually created.

play11:47

So in a sense, the scope chain is actually preserved

play11:51

through the closure, even when a scope

play11:54

has already been destroyed

play11:56

because its execution context is gone.

play11:59

This means that even though the execution context

play12:03

has actually been destroyed,

play12:04

the variable environment somehow keeps living

play12:07

somewhere in the engine.

play12:10

Now we can say that the Booker function closed over

play12:13

its parents scope or over its parent variable environment.

play12:18

And this includes all function arguments.

play12:21

Even though in this example, we don't have any.

play12:24

And now this attached or closed over variable environment

play12:28

stays with the function forever.

play12:31

It will carry it around and be able to use it forever.

play12:36

To make it a bit more digestible,

play12:38

we can also say that thanks to the closure,

play12:41

a function does not lose connection to variables

play12:45

that existed at the function's birthplace.

play12:48

That's a bit more intuitive, right?

play12:50

But anyway, let's see what happens now

play12:53

with execution of the Booker function.

play12:56

So the function attempts to increase

play12:59

the passengerCount variable.

play13:01

However, this variable is not in the current scope.

play13:05

And so JavaScript will immediately look into the closure

play13:09

and see if it can find the variable there.

play13:12

And it does this even before looking at the scope chain.

play13:16

For example, if there was a global passengerCount variable

play13:20

set to 10, it would still first use the one in the closure.

play13:25

So the closure basically has priority over the scope chain.

play13:30

And so after running this function,

play13:31

the passengerCount becomes one.

play13:34

This message is logged.

play13:35

And then the execution context is popped off the stack.

play13:40

Then execution moves to the next line.

play13:42

We get a new execution context and a closure is still there,

play13:46

still attached to the function and the value is still one.

play13:51

And so now this function executes,

play13:53

increasing the passengerCount to two

play13:56

and logging a message again.

play13:59

Okay, and that's what closures are

play14:02

and how they work behind the scenes.

play14:04

And I know that this is all quite complex.

play14:08

So let me give you a couple different definitions

play14:11

of closure now, some more formal ones

play14:14

and some more intuitive and maybe easier to grasp.

play14:19

And the most formal definition of closure

play14:21

is the one we already saw,

play14:23

which is that a closure is the closed over variable

play14:27

environment of the execution context

play14:30

in which a function was created

play14:32

even after that execution context is gone,

play14:36

or in other words, even after the function

play14:39

to which the execution context belongs has returned.

play14:44

Next and a bit easier to understand,

play14:47

a closure gives a function access to all the variables

play14:51

of its parent function.

play14:53

So the function in which it is defined

play14:56

even after that parent function has returned.

play15:00

So the function keeps a reference to its outer scope

play15:04

even after that outer scope is gone,

play15:07

which basically preserves the scope chain throughout time.

play15:12

All right, another definition,

play15:14

or let's say analogy is that a closure makes sure

play15:18

that a function does never lose connection

play15:21

to the variables that existed at the function's birthplace.

play15:25

It remembers the variables,

play15:27

even after the birthplace is gone.

play15:30

It's like a person who doesn't lose connection

play15:32

to their hometown.

play15:35

In this analogy, the person is the function

play15:38

and the hometown is the function's parents scope,

play15:42

and the function then doesn't lose the connection

play15:44

to the variables stored in this parent's scope.

play15:48

And I hope that makes sense.

play15:51

Finally, some people like to think of

play15:54

this attached variable environment as a backpack.

play15:58

So in this analogy, a function has a backpack,

play16:02

which it carries around wherever it goes.

play16:05

And this backpack contains all the variables

play16:08

that were present in the environment

play16:10

in which the function was created.

play16:13

Then whenever a variable can't be found

play16:16

in the function scope,

play16:17

JavaScript will look into the backpack

play16:20

and take the missing variable from there.

play16:23

So kind of similar to the other definitions,

play16:26

but maybe a little bit more visual.

play16:30

So these are some different ways of defining closure,

play16:34

but they all mean the same thing.

play16:36

So they all represent the same idea.

play16:39

Finally, we need to understand that we do not

play16:43

have to create closures manually.

play16:45

And this is also what I already touched on

play16:47

at the beginning of the lecture.

play16:50

So instead, this is something that JavaScript

play16:53

does completely automatically, we don't have to do anything.

play16:58

Also, there is no way for us to explicitly access

play17:02

closed over variables.

play17:04

That's because closures are not like a tangible thing.

play17:08

They're not like an object or so that we can access.

play17:12

So we cannot just reach into a closure

play17:14

and take variables from it.

play17:17

That's impossible because a closure

play17:19

is just an internal property of a function.

play17:23

We can observe that a closure happens

play17:26

because functions magically keep having access

play17:29

to variables that should no longer exist,

play17:32

but we cannot directly access these variables.

play17:36

However, what we can do is to actually take a look

play17:40

at this internal property.

play17:42

So at this backpack, so to say, in a console.

play17:46

So let's quickly do that before we finish this lecture.

play17:51

And we can do this by using console.dir

play17:58

and then of the Booker function itself.

play18:01

So similar to console.log

play18:03

but this one is a bit different.

play18:06

And so here we now get this function itself.

play18:11

So we can get the arguments, the name property

play18:14

that we already took a look at before.

play18:17

And then down here,

play18:18

we have this scope's internal property.

play18:21

And this internal scope's property here

play18:24

is basically the variable environment

play18:26

of the Booker function.

play18:29

Now in here, we can actually see the closure

play18:31

coming from secure booking, all right?

play18:35

And so this is where we see the passengerCount,

play18:38

which currently stands at three.

play18:41

And so this closure here basically,

play18:44

is the variable environment of this secure booking.

play18:50

So that's the one that is being preserved by the closure.

play18:55

All right?

play18:56

And by the way, whenever you see these double brackets here,

play19:01

that means that it is an internal property,

play19:04

which we cannot access from our code.

play19:07

All right, this was a long video about closures.

play19:11

Now in the next lecture,

play19:13

we're gonna take a look at three more examples

play19:16

of closures and also analyze how they work,

play19:19

because it's really important that you understand

play19:23

this concept of closures.

play19:25

It's a feature that's used all the time in JavaScript

play19:29

and many times, even without us realizing

play19:33

that closures are happening.

play19:35

So if you want to become confident as a programmer,

play19:38

you always need to know how exactly

play19:40

everything in your code works.

play19:43

And that of course includes closures.