All language subtitles for 137 Closures.en_US1

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranรฎ)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

There is an almost mystical feature

of Java script functions

that many developers fail to fully understand.

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

So when I asked my students,

what's the hardest JavaScript concept to understand,

then many people say that it's closures.

However, I believe that with the right explanation,

it's actually not that hard,

especially when you already understood everything

that you learned before in this course,

such as execution context,

the call stack, and the sculpt chain,

because closures kind of bring all of these concepts

together in a beautiful, almost magical way.

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

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

called secure booking.

And it is this function that will create the closure.

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

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

So we don't create closures manually,

like we create a new array or a new function.

So a closure simply happens automatically

in certain situations, we just need

to recognize those situations.

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

So we will create one of those situations

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

So anyway, let's now continue writing this example

and I'm calling this one passengerCount

and it will start at zero, but we will be

able to manipulate it.

And I'm calling this function here,

secure booking because this passengerCount variable

cannot be manipulated and accessed from the outside.

So, and now what's special about this function

is that it will return a new function.

And what we do in this function is to update

the passengerCount variable.

So the variable that is defined in the parent function.

So that's important.

And then let's just log the new passengerCount

to the console.

So passengerCount, alright,

and now let's call the secure booking function

and then store the result in a variable called Booker.

And so this is actually pretty similar to what we did

previously in the lecture of functions

returning other functions.

So we have one function here that we call

and this function will return this new function.

And so as we call secure booking,

it will return exactly this function

and it will then be stored inside this Booker.

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

So let's analyze in detail

what happens when this line of code here

is executed using all the concepts

that we already know about.

So this is exactly the code that we just wrote.

Now, before we start running

the secure booking function down here,

our code is running in the global execution context.

And in there, we currently only have

this secure booking function.

And so we can also say that the global scope

now contains secure booking.

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.

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 variable.

So the global context now also contains the Booker variable.

And now what else happens when

the 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.

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

and to keep in mind.

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

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

All we did was to analyze the call stack

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

And this is gonna be important to later on

understand the closure.

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

All we did was use the knowledge that we already have

to understand how this Booker function was created,

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

So let's now go back to our code

to actually use the Booker function,

and then finally see the closure in action.

So now that we understand how the Booker function

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

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

it doesn't need any arguments.

There's no list of parameters, right?

So let's call it here three times

and now let's reload the page here.

And indeed we get one, two, three passengers.

And so what this means is that the Booker function

was in fact able to increment the passengerCount

to one, then to two and then to three.

But now if we think about this,

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.

And maybe you can guess that what makes this possible

is a closure, but before I explain

exactly how the closure works,

I want you to appreciate once more,

how strange this actually is.

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.

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 so let me now, really explain how it actually works.

So this is how we left the call stack

and the sculpt chain after the last slide.

And the most important thing to notice here

is that the execution context of secure booking

is no longer on call stack,

because again, this function has finished

execution long ago.

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

and see exactly what's gonna happen here.

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

and the secret is basically this.

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

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.

For now, we are just trying to understand the mechanism

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

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 increase

the 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 two

and logging a message again.

Okay, and that's what closures are

and how they work behind the scenes.

And I know that this is all quite complex.

So let me give you a couple different definitions

of closure now, some more formal ones

and some more intuitive and maybe easier to grasp.

And the most formal definition of closure

is the one we already saw,

which is that a closure is the closed over variable

environment of the execution context

in which a function was created

even after that execution context is gone,

or in other words, even after the function

to which the execution context belongs has returned.

Next and a bit easier to understand,

a closure gives a function access to all the variables

of its parent function.

So the function in which it is defined

even after that parent function has returned.

So the function keeps a reference to its outer scope

even after that outer scope is gone,

which basically preserves the scope chain throughout time.

All right, another definition,

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

that a function does never lose connection

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

It remembers the variables,

even after the birthplace is gone.

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

to their hometown.

In this analogy, the person is the function

and the hometown is the function's parents scope,

and the function then doesn't lose the connection

to the variables stored in this parent's scope.

And I hope that makes sense.

Finally, some people like to think of

this attached variable environment as a backpack.

So in this analogy, 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.

Then whenever a variable can't be found

in the function scope,

JavaScript will look into the backpack

and take the missing variable from there.

So kind of similar to the other definitions,

but maybe a little bit more visual.

So these are some different ways of defining closure,

but they all mean the same thing.

So they all represent the same idea.

Finally, we need to understand that we do not

have to create closures manually.

And this is also what I already touched on

at the beginning of the lecture.

So instead, this is something that JavaScript

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

Also, there is no way for us to explicitly access

closed over variables.

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

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

So we cannot just reach into a closure

and take variables from it.

That's impossible because a closure

is just an internal property of a function.

We can observe that a closure happens

because functions magically keep having access

to variables that should no longer exist,

but we cannot directly access these variables.

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

at this internal property.

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

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

And we can do this by using console.dir

and then of the Booker function itself.

So similar to console.log

but this one is a bit different.

And so here we now get this function itself.

So we can get the arguments, the name property

that we already took a look at before.

And then down here,

we have this scope's internal property.

And this internal scope's property here

is basically the variable environment

of the Booker function.

Now in here, we can actually see the closure

coming from secure booking, all right?

And so this is where we see the passengerCount,

which currently stands at three.

And so this closure here basically,

is the variable environment of this secure booking.

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

All right?

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

that means that it is an internal property,

which we cannot access from our code.

All right, this was a long video about closures.

Now in the next lecture,

we're gonna take a look at three more examples

of closures and also analyze how they work,

because it's really important that you understand

this concept of closures.

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

and many times, even without us realizing

that closures are happening.

So if you want to become confident as a programmer,

you always need to know how exactly

everything in your code works.

And that of course includes closures.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.