Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
French
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
1 1
There is an almost mystical feature 2
2
of Java script functions 3
3
that many developers fail to fully understand. 4
4
And what I'm talking about is something called closures. 5
5
So when I asked my students, 6
6
what's the hardest JavaScript concept to understand, 7
7
then many people say that it's closures. 8
8
However, I believe that with the right explanation, 9
9
it's actually not that hard, 10
10
especially when you already understood everything 11
11
that you learned before in this course, 12
12
such as execution context, 13
13
the call stack, and the sculpt chain, 14
14
because closures kind of bring all of these concepts 15
15
together in a beautiful, almost magical way. 16
16
So enough talk, let's see what closures are all about. 17
17
So I'm gonna start by creating a new function here 18
18
called secure booking. 19
19
And it is this function that will create the closure. 20
20
Now, the first thing that I need to tell you about closures 21
21
is that a closure is not a feature that we explicitly use. 22
22
So we don't create closures manually, 23
23
like we create a new array or a new function. 24
24
So a closure simply happens automatically 25
25
in certain situations, we just need 26
26
to recognize those situations. 27
27
And so that's what we're gonna do here in this example. 28
28
So we will create one of those situations 29
29
so that we can then take a look at a closure. 30
30
So anyway, let's now continue writing this example 31
31
and I'm calling this one passengerCount 32
32
and it will start at zero, but we will be 33
33
able to manipulate it. 34
34
And I'm calling this function here, 35
35
secure booking because this passengerCount variable 36
36
cannot be manipulated and accessed from the outside. 37
37
So, and now what's special about this function 38
38
is that it will return a new function. 39
39
And what we do in this function is to update 40
40
the passengerCount variable. 41
41
So the variable that is defined in the parent function. 42
42
So that's important. 43
43
And then let's just log the new passengerCount 44
44
to the console. 45
45
So passengerCount, alright, 46
46
and now let's call the secure booking function 47
47
and then store the result in a variable called Booker. 48
48
And so this is actually pretty similar to what we did 49
49
previously in the lecture of functions 50
50
returning other functions. 51
51
So we have one function here that we call 52
52
and this function will return this new function. 53
53
And so as we call secure booking, 54
54
it will return exactly this function 55
55
and it will then be stored inside this Booker. 56
56
And so this here is gonna be now a function as well, right? 57
57
So let's analyze in detail 58
58
what happens when this line of code here 59
59
is executed using all the concepts 60
60
that we already know about. 61
61
So this is exactly the code that we just wrote. 62
62
Now, before we start running 63
63
the secure booking function down here, 64
64
our code is running in the global execution context. 65
65
And in there, we currently only have 66
66
this secure booking function. 67
67
And so we can also say that the global scope 68
68
now contains secure booking. 69
69
Then when secure booking is actually executed, 70
70
a new execution context is put 71
71
on top of the execution stack. 72
72
Now, remember, each execution context 73
73
has a variable environment, 74
74
which contains all its local variables. 75
75
In this case, it only contains the passengerCount 76
76
set to zero. 77
77
This variable environment is also 78
78
the scope of this function. 79
79
And so the scope chain of this execution context 80
80
looks like this. 81
81
So passengerCount is in the local scope, 82
82
but of course this scope also gets access 83
83
to all variables of the parent's scopes. 84
84
And in this case, just a global scope. 85
85
Anyway, in the next line of the secure booking function, 86
86
a new function is returned and it will be stored 87
87
in the Booker variable. 88
88
So the global context now also contains the Booker variable. 89
89
And now what else happens when 90
90
the secure booking function returns? 91
91
Well, that's right. 92
92
Its execution context pops off the stack and disappears. 93
93
So the secure booking function has done its job 94
94
and has now finished execution. 95
95
It really is gone now and that's important to be aware of 96
96
and to keep in mind. 97
97
And for now, that's actually all we did. 98
98
So all this is nothing new at this point, right? 99
99
All we did was to analyze the call stack 100
100
and the scope chain as we call the secure booking function. 101
101
And this is gonna be important to later on 102
102
understand the closure. 103
103
So as of yet, we didn't see the closure yet. 104
104
All we did was use the knowledge that we already have 105
105
to understand how this Booker function was created, 106
106
because that's gonna be important for the next step. 107
107
So let's now go back to our code 108
108
to actually use the Booker function, 109
109
and then finally see the closure in action. 110
110
So now that we understand how the Booker function 111
111
was created, let's now actually call it here. 112
112
So calling it a couple of times here, and as we can see, 113
113
it doesn't need any arguments. 114
114
There's no list of parameters, right? 115
115
So let's call it here three times 116
116
and now let's reload the page here. 117
117
And indeed we get one, two, three passengers. 118
118
And so what this means is that the Booker function 119
119
was in fact able to increment the passengerCount 120
120
to one, then to two and then to three. 121
121
But now if we think about this, 122
122
then how is this even possible? 123
123
How can the Booker function update 124
124
this passengerCount variable that's defined 125
125
in a secure booking function 126
126
that actually has already finished executing. 127
127
And so, as I just said, 128
128
this function has already finished its execution. 129
129
It is gone. 130
130
So its execution context is no longer on the stack, 131
131
as we just saw in the slide, 132
132
but still this inner function here, 133
133
which is the Booker function, 134
134
is still able to access the passengerCount variable 135
135
that's inside of the Booker function 136
136
that should no longer exist. 137
137
And maybe you can guess that what makes this possible 138
138
is a closure, but before I explain 139
139
exactly how the closure works, 140
140
I want you to appreciate once more, 141
141
how strange this actually is. 142
142
So again, this Booker function here 143
143
is simply a function that exists 144
144
out here in the global environment 145
145
or in the global scope, right? 146
146
And the environment in which the function was created. 147
147
So this year basically, this environment 148
148
is no longer active. 149
149
It is in fact gone. 150
150
But still the Booker function somehow continues 151
151
to have access to the variables 152
152
that were present at the time that the function was created. 153
153
And in particular, this passengerCount variable here. 154
154
And so that's exactly what the closure does. 155
155
So we can say that a closure makes a function 156
156
remember all the variables that existed 157
157
at the function's birthplace essentially, right? 158
158
So we can imagine the secure booking 159
159
as being the birthplace of this function. 160
160
So of the Booker function, essentially. 161
161
And so this function remembers everything at its birthplace, 162
162
by the time it was created. 163
163
And this cannot simply be explained 164
164
with the scope chain alone. 165
165
So we need to also understand the closure. 166
166
And so let me now, really explain how it actually works. 167
167
So this is how we left the call stack 168
168
and the sculpt chain after the last slide. 169
169
And the most important thing to notice here 170
170
is that the execution context of secure booking 171
171
is no longer on call stack, 172
172
because again, this function has finished 173
173
execution long ago. 174
174
So now it's time to finally run the Booker function 175
175
and see exactly what's gonna happen here. 176
176
And note that Booker is really this function here, 177
177
located in the global scope. 178
178
Anyway, the first thing that's gonna happen 179
179
is that a new execution context is created 180
180
and put on top of the call stack 181
181
and the variable environment of this context is emptied 182
182
simply because there are no variables 183
183
declared in this function. 184
184
Now what about the scope chain? 185
185
Well, since Booker is in the global context, 186
186
it's simply a child's scope of the global scope, 187
187
just like this, but maybe now 188
188
you're starting to see the problem. 189
189
So how will the Booker function access 190
190
the passengerCount variable? 191
191
It's nowhere to be found in the scope chain, right? 192
192
So this is where we start to unveil 193
193
the secret of the closure 194
194
and the secret is basically this. 195
195
Any function always has access to the variable environment 196
196
of the execution context in which the function was created. 197
197
Now, in the case of Booker, this function was created. 198
198
It was born in the execution context of secure booking, 199
199
which was popped off the stack previously, remember? 200
200
So, therefore the Booker function 201
201
will get access to this variable environment, 202
202
which contains the passengerCount variable. 203
203
And this is how the function will be able to read 204
204
and manipulate the passengerCount variable. 205
205
And so it's this connection that we call closure. 206
206
So let's say all that again, to make this really clear. 207
207
So a function always has access to the variable environment 208
208
of the execution context in which it was created, 209
209
even after a debt execution context is gone. 210
210
And this last part is really important. 211
211
The closure is then basically this variable environment 212
212
attached to the function, 213
213
exactly as it was at the time and place 214
214
that the function was created. 215
215
And this probably still sounds confusing, but don't worry. 216
216
I have some more familiar analogies in the next slide. 217
217
For now, we are just trying to understand the mechanism 218
218
behind the closure, so how it all works behind the scenes. 219
219
So what matters the most here is that the Booker function 220
220
has access to the passengerCount variable 221
221
because it's basically defined in the scope 222
222
in which the Booker function was actually created. 223
223
So in a sense, the scope chain is actually preserved 224
224
through the closure, even when a scope 225
225
has already been destroyed 226
226
because its execution context is gone. 227
227
This means that even though the execution context 228
228
has actually been destroyed, 229
229
the variable environment somehow keeps living 230
230
somewhere in the engine. 231
231
Now we can say that the Booker function closed over 232
232
its parents scope or over its parent variable environment. 233
233
And this includes all function arguments. 234
234
Even though in this example, we don't have any. 235
235
And now this attached or closed over variable environment 236
236
stays with the function forever. 237
237
It will carry it around and be able to use it forever. 238
238
To make it a bit more digestible, 239
239
we can also say that thanks to the closure, 240
240
a function does not lose connection to variables 241
241
that existed at the function's birthplace. 242
242
That's a bit more intuitive, right? 243
243
But anyway, let's see what happens now 244
244
with execution of the Booker function. 245
245
So the function attempts to increase 246
246
the passengerCount variable. 247
247
However, this variable is not in the current scope. 248
248
And so JavaScript will immediately look into the closure 249
249
and see if it can find the variable there. 250
250
And it does this even before looking at the scope chain. 251
251
For example, if there was a global passengerCount variable 252
252
set to 10, it would still first use the one in the closure. 253
253
So the closure basically has priority over the scope chain. 254
254
And so after running this function, 255
255
the passengerCount becomes one. 256
256
This message is logged. 257
257
And then the execution context is popped off the stack. 258
258
Then execution moves to the next line. 259
259
We get a new execution context and a closure is still there, 260
260
still attached to the function and the value is still one. 261
261
And so now this function executes, 262
262
increasing the passengerCount to two 263
263
and logging a message again. 264
264
Okay, and that's what closures are 265
265
and how they work behind the scenes. 266
266
And I know that this is all quite complex. 267
267
So let me give you a couple different definitions 268
268
of closure now, some more formal ones 269
269
and some more intuitive and maybe easier to grasp. 270
270
And the most formal definition of closure 271
271
is the one we already saw, 272
272
which is that a closure is the closed over variable 273
273
environment of the execution context 274
274
in which a function was created 275
275
even after that execution context is gone, 276
276
or in other words, even after the function 277
277
to which the execution context belongs has returned. 278
278
Next and a bit easier to understand, 279
279
a closure gives a function access to all the variables 280
280
of its parent function. 281
281
So the function in which it is defined 282
282
even after that parent function has returned. 283
283
So the function keeps a reference to its outer scope 284
284
even after that outer scope is gone, 285
285
which basically preserves the scope chain throughout time. 286
286
All right, another definition, 287
287
or let's say analogy is that a closure makes sure 288
288
that a function does never lose connection 289
289
to the variables that existed at the function's birthplace. 290
290
It remembers the variables, 291
291
even after the birthplace is gone. 292
292
It's like a person who doesn't lose connection 293
293
to their hometown. 294
294
In this analogy, the person is the function 295
295
and the hometown is the function's parents scope, 296
296
and the function then doesn't lose the connection 297
297
to the variables stored in this parent's scope. 298
298
And I hope that makes sense. 299
299
Finally, some people like to think of 300
300
this attached variable environment as a backpack. 301
301
So in this analogy, a function has a backpack, 302
302
which it carries around wherever it goes. 303
303
And this backpack contains all the variables 304
304
that were present in the environment 305
305
in which the function was created. 306
306
Then whenever a variable can't be found 307
307
in the function scope, 308
308
JavaScript will look into the backpack 309
309
and take the missing variable from there. 310
310
So kind of similar to the other definitions, 311
311
but maybe a little bit more visual. 312
312
So these are some different ways of defining closure, 313
313
but they all mean the same thing. 314
314
So they all represent the same idea. 315
315
Finally, we need to understand that we do not 316
316
have to create closures manually. 317
317
And this is also what I already touched on 318
318
at the beginning of the lecture. 319
319
So instead, this is something that JavaScript 320
320
does completely automatically, we don't have to do anything. 321
321
Also, there is no way for us to explicitly access 322
322
closed over variables. 323
323
That's because closures are not like a tangible thing. 324
324
They're not like an object or so that we can access. 325
325
So we cannot just reach into a closure 326
326
and take variables from it. 327
327
That's impossible because a closure 328
328
is just an internal property of a function. 329
329
We can observe that a closure happens 330
330
because functions magically keep having access 331
331
to variables that should no longer exist, 332
332
but we cannot directly access these variables. 333
333
However, what we can do is to actually take a look 334
334
at this internal property. 335
335
So at this backpack, so to say, in a console. 336
336
So let's quickly do that before we finish this lecture. 337
337
And we can do this by using console.dir 338
338
and then of the Booker function itself. 339
339
So similar to console.log 340
340
but this one is a bit different. 341
341
And so here we now get this function itself. 342
342
So we can get the arguments, the name property 343
343
that we already took a look at before. 344
344
And then down here, 345
345
we have this scope's internal property. 346
346
And this internal scope's property here 347
347
is basically the variable environment 348
348
of the Booker function. 349
349
Now in here, we can actually see the closure 350
350
coming from secure booking, all right? 351
351
And so this is where we see the passengerCount, 352
352
which currently stands at three. 353
353
And so this closure here basically, 354
354
is the variable environment of this secure booking. 355
355
So that's the one that is being preserved by the closure. 356
356
All right? 357
357
And by the way, whenever you see these double brackets here, 358
358
that means that it is an internal property, 359
359
which we cannot access from our code. 360
360
All right, this was a long video about closures. 361
361
Now in the next lecture, 362
362
we're gonna take a look at three more examples 363
363
of closures and also analyze how they work, 364
364
because it's really important that you understand 365
365
this concept of closures. 366
366
It's a feature that's used all the time in JavaScript 367
367
and many times, even without us realizing 368
368
that closures are happening. 369
369
So if you want to become confident as a programmer, 370
370
you always need to know how exactly 371
371
everything in your code works. 372
372
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.