Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
1
00:00:00,840 --> 00:00:03,090
Let's continue our journey
2
2
00:00:03,090 --> 00:00:07,330
of diving really deep into how JavaScript actually works
3
3
00:00:07,330 --> 00:00:08,960
behind the scenes.
4
4
00:00:08,960 --> 00:00:11,450
I really hope you have enjoyed it so far
5
5
00:00:11,450 --> 00:00:14,370
and are able to see the immense value
6
6
00:00:14,370 --> 00:00:17,460
that these lectures bring to the table.
7
7
00:00:17,460 --> 00:00:19,170
Now, after this lecture,
8
8
00:00:19,170 --> 00:00:22,560
there will finally be another coding lecture.
9
9
00:00:22,560 --> 00:00:25,223
So hang tight, we're almost there.
10
10
00:00:27,070 --> 00:00:30,770
But now let's get started with this lecture.
11
11
00:00:30,770 --> 00:00:33,430
So we learned in the last lecture
12
12
00:00:33,430 --> 00:00:37,810
that each execution context has a variable environment,
13
13
00:00:37,810 --> 00:00:41,340
a scope chain and a this keyword.
14
14
00:00:41,340 --> 00:00:44,510
So in this lecture, let's learn what scope
15
15
00:00:44,510 --> 00:00:46,200
and a scope chain are,
16
16
00:00:46,200 --> 00:00:49,970
why they are so important and how they work.
17
17
00:00:49,970 --> 00:00:51,930
And let's start by understanding
18
18
00:00:51,930 --> 00:00:54,190
what scoping actually means,
19
19
00:00:54,190 --> 00:00:57,930
and learn about some related concepts as well.
20
20
00:00:57,930 --> 00:01:02,250
So scoping controls how our program's variables
21
21
00:01:02,250 --> 00:01:06,293
are organized and accessed by the JavaScript engine.
22
22
00:01:07,140 --> 00:01:10,430
So basically scoping asks the question,
23
23
00:01:10,430 --> 00:01:12,560
where do variables live?
24
24
00:01:12,560 --> 00:01:16,993
Or where can we access a certain variable and where not?
25
25
00:01:18,030 --> 00:01:19,330
Now in JavaScript,
26
26
00:01:19,330 --> 00:01:22,720
we have something called lexical scoping.
27
27
00:01:22,720 --> 00:01:26,060
And lexical scoping means that the way variables
28
28
00:01:26,060 --> 00:01:28,330
are organized and accessed
29
29
00:01:28,330 --> 00:01:32,400
is entirely controlled by the placement of functions
30
30
00:01:32,400 --> 00:01:35,710
and of blocks in the programs code.
31
31
00:01:35,710 --> 00:01:39,470
For example, a function that is written inside
32
32
00:01:39,470 --> 00:01:42,940
another function has access to the variables
33
33
00:01:42,940 --> 00:01:45,930
of the parent function, okay?
34
34
00:01:45,930 --> 00:01:49,550
So again, variable scoping is influenced
35
35
00:01:49,550 --> 00:01:54,550
by where exactly we write our functions and code blocks.
36
36
00:01:55,120 --> 00:01:58,370
Okay, and now about scope itself.
37
37
00:01:58,370 --> 00:02:01,300
Scope is the space or environment
38
38
00:02:01,300 --> 00:02:04,430
in which a certain variable is declared,
39
39
00:02:04,430 --> 00:02:06,230
simple as that.
40
40
00:02:06,230 --> 00:02:08,050
And in the case of functions,
41
41
00:02:08,050 --> 00:02:10,870
that's essentially the variable environment
42
42
00:02:10,870 --> 00:02:15,020
which is stored in the functions execution context.
43
43
00:02:15,020 --> 00:02:17,210
So if now you're asking yourself,
44
44
00:02:17,210 --> 00:02:19,460
what's the difference between scope
45
45
00:02:19,460 --> 00:02:21,770
and variable environment?
46
46
00:02:21,770 --> 00:02:25,510
Then the answer is that for the case of functions,
47
47
00:02:25,510 --> 00:02:27,730
it's basically the same.
48
48
00:02:27,730 --> 00:02:30,770
Now in JavaScript, we have the global scope,
49
49
00:02:30,770 --> 00:02:33,690
function scope, and block scope.
50
50
00:02:33,690 --> 00:02:36,340
And we will talk about these in a second.
51
51
00:02:36,340 --> 00:02:39,560
But first, let's also define what the scope
52
52
00:02:39,560 --> 00:02:41,620
of a variable is.
53
53
00:02:41,620 --> 00:02:46,590
So the scope of a variable is basically the entire region
54
54
00:02:46,590 --> 00:02:51,170
of our code, where a certain variable can be accessed.
55
55
00:02:51,170 --> 00:02:55,170
Now, some people use the word scope for all of this,
56
56
00:02:55,170 --> 00:02:58,600
but I like to define all these concepts that we have here
57
57
00:02:58,600 --> 00:03:03,160
in a clear way, because actually subtle differences.
58
58
00:03:03,160 --> 00:03:06,070
For example, if you take a close look at it,
59
59
00:03:06,070 --> 00:03:09,940
scope is not the same as scope of a variable.
60
60
00:03:09,940 --> 00:03:14,430
And so you should know about the subtle differences, right?
61
61
00:03:14,430 --> 00:03:18,240
And I know it might still sound all the same for now,
62
62
00:03:18,240 --> 00:03:21,040
but after looking at a couple of examples
63
63
00:03:21,040 --> 00:03:23,050
and writing some real code,
64
64
00:03:23,050 --> 00:03:26,563
you will understand everything I just showed you here.
65
65
00:03:27,840 --> 00:03:31,000
Anyway, let's now talk about the three different types
66
66
00:03:31,000 --> 00:03:33,470
of scope in JavaScript.
67
67
00:03:33,470 --> 00:03:38,470
So that's global scope, function scope and block scope.
68
68
00:03:38,750 --> 00:03:42,030
And remember, scope is the place in our code
69
69
00:03:42,030 --> 00:03:44,940
where variables are declared.
70
70
00:03:44,940 --> 00:03:48,310
And when I say variables, the exact same thing
71
71
00:03:48,310 --> 00:03:50,800
is true for functions as well.
72
72
00:03:50,800 --> 00:03:54,420
Because in the end, functions are just values
73
73
00:03:54,420 --> 00:03:56,990
that are stored in variables.
74
74
00:03:56,990 --> 00:04:01,120
So first, the global scope is once more
75
75
00:04:01,120 --> 00:04:03,430
for top level code.
76
76
00:04:03,430 --> 00:04:06,270
So this is for variables that are declared
77
77
00:04:06,270 --> 00:04:09,930
outside of any function or block.
78
78
00:04:09,930 --> 00:04:12,840
These variables will be accessible everywhere
79
79
00:04:12,840 --> 00:04:17,050
in our program, in all functions and all blocks.
80
80
00:04:17,050 --> 00:04:19,830
So really, everywhere.
81
81
00:04:19,830 --> 00:04:23,730
Next, each and every function creates a scope.
82
82
00:04:23,730 --> 00:04:27,120
And the variables declared inside that function scope
83
83
00:04:27,120 --> 00:04:30,230
are only accessible inside that function.
84
84
00:04:30,230 --> 00:04:33,230
This is also called a local scope
85
85
00:04:33,230 --> 00:04:35,800
opposed to the global scope.
86
86
00:04:35,800 --> 00:04:40,150
So local variables live in the function so to say.
87
87
00:04:40,150 --> 00:04:41,920
And outside of the function,
88
88
00:04:41,920 --> 00:04:45,740
the variables are then not accessible at all.
89
89
00:04:45,740 --> 00:04:48,390
Again, this is technically the same
90
90
00:04:48,390 --> 00:04:51,130
as the functions variable environment,
91
91
00:04:51,130 --> 00:04:54,280
but we still need to give it the name of scope
92
92
00:04:54,280 --> 00:04:55,510
in this context,
93
93
00:04:55,510 --> 00:04:58,610
because blocks also creates scopes.
94
94
00:04:58,610 --> 00:05:01,010
Anyway, in this example here,
95
95
00:05:01,010 --> 00:05:06,010
the now variable is 2037 inside the cog H function.
96
96
00:05:06,560 --> 00:05:09,240
And therefore, we can use it in the function
97
97
00:05:09,240 --> 00:05:10,960
to do calculations.
98
98
00:05:10,960 --> 00:05:13,260
But outside of the function,
99
99
00:05:13,260 --> 00:05:15,730
as we try to log it to the console,
100
100
00:05:15,730 --> 00:05:18,440
we get a reference error.
101
101
00:05:18,440 --> 00:05:22,010
So JavaScript is trying to find the now variable
102
102
00:05:22,010 --> 00:05:23,770
in this global scope,
103
103
00:05:23,770 --> 00:05:27,370
so outside of the function, but it cannot find it.
104
104
00:05:27,370 --> 00:05:29,750
And so there is gonna be an error.
105
105
00:05:29,750 --> 00:05:32,430
And if you remember, or pick game project
106
106
00:05:32,430 --> 00:05:34,060
from the previous section,
107
107
00:05:34,060 --> 00:05:36,820
there is also the reason why we had to declare
108
108
00:05:36,820 --> 00:05:41,080
a couple of variables outside of the init function,
109
109
00:05:41,080 --> 00:05:42,410
remember that?
110
110
00:05:42,410 --> 00:05:45,920
So we had some variables declared in the init function,
111
111
00:05:45,920 --> 00:05:47,570
and then that gave us an error
112
112
00:05:47,570 --> 00:05:50,030
because other functions were trying
113
113
00:05:50,030 --> 00:05:51,860
to access these variables.
114
114
00:05:51,860 --> 00:05:54,580
But of course they were in the function scope.
115
115
00:05:54,580 --> 00:05:56,860
And so they were locally scoped,
116
116
00:05:56,860 --> 00:05:58,210
and so we couldn't access them
117
117
00:05:58,210 --> 00:06:02,400
outside of that function where they were declared.
118
118
00:06:02,400 --> 00:06:04,610
And here, it actually does not matter
119
119
00:06:04,610 --> 00:06:07,230
what kind of function we're using.
120
120
00:06:07,230 --> 00:06:10,380
So function declarations, function expressions
121
121
00:06:10,380 --> 00:06:14,223
and arrow functions all create their own scope.
122
122
00:06:15,260 --> 00:06:19,500
Now traditionally, only functions used to create scopes
123
123
00:06:19,500 --> 00:06:20,850
in JavaScript.
124
124
00:06:20,850 --> 00:06:25,850
But starting in ES6, blocks also creates scopes now.
125
125
00:06:25,860 --> 00:06:26,810
And with blocks,
126
126
00:06:26,810 --> 00:06:29,970
we mean everything that is between curly braces,
127
127
00:06:29,970 --> 00:06:34,510
such as the block of an if statement or a for loop.
128
128
00:06:34,510 --> 00:06:36,920
So just like with functions,
129
129
00:06:36,920 --> 00:06:39,570
variables declared inside a block
130
130
00:06:39,570 --> 00:06:42,350
are only accessible inside that block
131
131
00:06:42,350 --> 00:06:44,970
and not outside of it.
132
132
00:06:44,970 --> 00:06:47,950
Now, the big difference is that block scopes
133
133
00:06:47,950 --> 00:06:52,950
only apply to variables declared with let or const, okay?
134
134
00:06:53,540 --> 00:06:57,500
So again, only let and const variables
135
135
00:06:57,500 --> 00:07:01,600
are restricted to the block in which they were created.
136
136
00:07:01,600 --> 00:07:04,910
That's why we say that let and const variables
137
137
00:07:04,910 --> 00:07:06,710
are block scoped.
138
138
00:07:06,710 --> 00:07:10,890
So if I declared a variable using var in this block,
139
139
00:07:10,890 --> 00:07:14,520
then that variable would actually still be accessible
140
140
00:07:14,520 --> 00:07:16,550
outside of the block,
141
141
00:07:16,550 --> 00:07:19,430
and would be scoped to the current function
142
142
00:07:19,430 --> 00:07:21,410
or to the global scope.
143
143
00:07:21,410 --> 00:07:25,570
And so we say that var is function scoped.
144
144
00:07:25,570 --> 00:07:27,970
So in ES5 and before,
145
145
00:07:27,970 --> 00:07:31,260
we only had global scope and function scope.
146
146
00:07:31,260 --> 00:07:35,400
And that's why ES5 variables declared with var,
147
147
00:07:35,400 --> 00:07:39,080
only care about functions, but not about blocks.
148
148
00:07:39,080 --> 00:07:40,960
They simply ignore them.
149
149
00:07:40,960 --> 00:07:44,170
Finally, also starting in ES6,
150
150
00:07:44,170 --> 00:07:47,070
all functions are now also block scoped,
151
151
00:07:47,070 --> 00:07:49,010
at least in strict mode,
152
152
00:07:49,010 --> 00:07:52,040
which you should always be using anyway.
153
153
00:07:52,040 --> 00:07:55,420
And just like with let and const variables,
154
154
00:07:55,420 --> 00:07:58,750
this means that functions declared inside a block
155
155
00:07:58,750 --> 00:08:03,410
are only accessible inside that block, okay?
156
156
00:08:03,410 --> 00:08:06,730
And we will see examples of all that in the next video,
157
157
00:08:06,730 --> 00:08:09,023
when we're gonna go back to coding.
158
158
00:08:10,230 --> 00:08:13,930
So to recap, let and const variables
159
159
00:08:13,930 --> 00:08:17,260
as well as functions are block scoped.
160
160
00:08:17,260 --> 00:08:20,440
And if you already know other programming languages,
161
161
00:08:20,440 --> 00:08:23,090
block scoping is probably more in line
162
162
00:08:23,090 --> 00:08:25,230
with what you already know.
163
163
00:08:25,230 --> 00:08:28,680
Function scopes are weird for some beginners
164
164
00:08:28,680 --> 00:08:30,400
in the JavaScript world.
165
165
00:08:30,400 --> 00:08:35,070
And that's why block scopes were introduced in ES6.
166
166
00:08:35,070 --> 00:08:38,440
But now to understand all this a little bit better,
167
167
00:08:38,440 --> 00:08:42,560
let's actually look at a more real and detailed example
168
168
00:08:42,560 --> 00:08:45,493
and also learn about the scope chain.
169
169
00:08:47,520 --> 00:08:50,520
And here we have some code with different functions
170
170
00:08:50,520 --> 00:08:51,650
and blocks,
171
171
00:08:51,650 --> 00:08:53,720
and we're gonna take a look at the scopes
172
172
00:08:53,720 --> 00:08:58,330
that are in this code as well as build the scope chain.
173
173
00:08:58,330 --> 00:09:02,290
And of course, we start with the global scope.
174
174
00:09:02,290 --> 00:09:05,030
As you can see, the myName variable
175
175
00:09:05,030 --> 00:09:07,360
is the only variable declaration
176
176
00:09:07,360 --> 00:09:10,100
that we have in the global scope.
177
177
00:09:10,100 --> 00:09:12,600
Now, technically, the first function
178
178
00:09:12,600 --> 00:09:14,700
also counts as a variable
179
179
00:09:14,700 --> 00:09:17,010
that is present in the global scope,
180
180
00:09:17,010 --> 00:09:18,870
but I want to keep it simple here.
181
181
00:09:18,870 --> 00:09:22,180
And so I will only consider variable declarations
182
182
00:09:22,180 --> 00:09:24,510
and no functions, all right?
183
183
00:09:24,510 --> 00:09:27,500
Just keep in mind that whatever I'm explaining here
184
184
00:09:27,500 --> 00:09:31,363
for variables also works the same for functions.
185
185
00:09:32,310 --> 00:09:35,020
Anyway, inside the global scope,
186
186
00:09:35,020 --> 00:09:38,220
we have a scope for the first function
187
187
00:09:38,220 --> 00:09:42,820
because each function creates its own scope, remember?
188
188
00:09:42,820 --> 00:09:44,970
And what's in the scope?
189
189
00:09:44,970 --> 00:09:47,870
Well, it's to age variable that's declared
190
190
00:09:47,870 --> 00:09:50,500
right at the top of the function.
191
191
00:09:50,500 --> 00:09:52,960
Next inside the first scope,
192
192
00:09:52,960 --> 00:09:55,670
let's now consider the second function,
193
193
00:09:55,670 --> 00:09:58,270
which will also create its own scope
194
194
00:09:58,270 --> 00:10:01,820
containing the job variable set to teacher.
195
195
00:10:01,820 --> 00:10:03,060
So as you see,
196
196
00:10:03,060 --> 00:10:06,400
we have a nested structure of scopes
197
197
00:10:06,400 --> 00:10:09,490
with one scope inside the other.
198
198
00:10:09,490 --> 00:10:12,680
But now comes the actually interesting part.
199
199
00:10:12,680 --> 00:10:15,200
Because here in the second function,
200
200
00:10:15,200 --> 00:10:17,180
we have this line of code
201
201
00:10:17,180 --> 00:10:19,810
where we need the myName variable
202
202
00:10:19,810 --> 00:10:21,610
and the age variable,
203
203
00:10:21,610 --> 00:10:26,070
which were both not declared inside the current scope.
204
204
00:10:26,070 --> 00:10:28,720
But we really need these variables here,
205
205
00:10:28,720 --> 00:10:33,530
because otherwise we can't create this string here, right?
206
206
00:10:33,530 --> 00:10:35,700
So how can this be fixed?
207
207
00:10:35,700 --> 00:10:38,890
How will the JavaScript engine know the values
208
208
00:10:38,890 --> 00:10:40,970
of these variables?
209
209
00:10:40,970 --> 00:10:43,730
Well, the secret is that every scope
210
210
00:10:43,730 --> 00:10:46,520
always has access to all the variables
211
211
00:10:46,520 --> 00:10:49,050
from all its outer scopes.
212
212
00:10:49,050 --> 00:10:51,710
So from all its parent scopes.
213
213
00:10:51,710 --> 00:10:54,970
In our example, this means that the second scope
214
214
00:10:54,970 --> 00:10:57,950
can access the age variable from the scope
215
215
00:10:57,950 --> 00:10:59,900
of the first function.
216
216
00:10:59,900 --> 00:11:03,010
Of course, this also means that the first scope
217
217
00:11:03,010 --> 00:11:06,690
can access variables that are in the global scope,
218
218
00:11:06,690 --> 00:11:09,560
because that is the parent scope.
219
219
00:11:09,560 --> 00:11:11,480
As a consequence of this,
220
220
00:11:11,480 --> 00:11:14,870
the second scope will then also be able to access
221
221
00:11:14,870 --> 00:11:18,140
the myName variable from the global scope,
222
222
00:11:18,140 --> 00:11:21,030
because it has access to the variables
223
223
00:11:21,030 --> 00:11:22,713
from the first scope.
224
224
00:11:23,670 --> 00:11:28,180
And by the way, all this also applies to function arguments.
225
225
00:11:28,180 --> 00:11:31,043
But in this example, we just don't have any.
226
226
00:11:31,900 --> 00:11:36,590
And this is essentially how the scope chain works.
227
227
00:11:36,590 --> 00:11:37,650
In other words,
228
228
00:11:37,650 --> 00:11:41,130
if one scope needs to use a certain variable,
229
229
00:11:41,130 --> 00:11:43,940
but cannot find it in the current scope,
230
230
00:11:43,940 --> 00:11:46,460
it will look up in the scope chain
231
231
00:11:46,460 --> 00:11:48,840
and see if it can find a variable
232
232
00:11:48,840 --> 00:11:51,060
in one of the parent scopes.
233
233
00:11:51,060 --> 00:11:54,160
If it can, it will then use that variable.
234
234
00:11:54,160 --> 00:11:57,620
And if it can't, then there will be an error.
235
235
00:11:57,620 --> 00:12:00,503
And this process is called variable lookup.
236
236
00:12:01,870 --> 00:12:04,710
Now it's important to note that these variables
237
237
00:12:04,710 --> 00:12:09,460
are not copied from one scope to another, okay?
238
238
00:12:09,460 --> 00:12:13,190
Instead, scopes simply look up in the scope chain
239
239
00:12:13,190 --> 00:12:15,970
until they find a variable that they need
240
240
00:12:15,970 --> 00:12:17,940
and then they use it.
241
241
00:12:17,940 --> 00:12:20,760
What's also extremely important to note
242
242
00:12:20,760 --> 00:12:24,240
is that this does not work the other way around.
243
243
00:12:24,240 --> 00:12:27,560
A certain scope will never, ever have access
244
244
00:12:27,560 --> 00:12:29,940
to the variables of an inner scope.
245
245
00:12:29,940 --> 00:12:33,650
In this example, the first scope, for example,
246
246
00:12:33,650 --> 00:12:36,900
will never get access to the job variable
247
247
00:12:36,900 --> 00:12:40,840
that is stored in the second scope, okay?
248
248
00:12:40,840 --> 00:12:45,460
So again, one scope can only look up in a scope chain,
249
249
00:12:45,460 --> 00:12:48,520
but it cannot look down basically.
250
250
00:12:48,520 --> 00:12:50,840
So only parent scope can be used,
251
251
00:12:50,840 --> 00:12:52,603
but no child scopes.
252
252
00:12:53,450 --> 00:12:56,220
Anyway, with all this in place now,
253
253
00:12:56,220 --> 00:12:58,690
this line of code can be executed
254
254
00:12:58,690 --> 00:13:00,400
and print to the console.
255
255
00:13:00,400 --> 00:13:03,390
Jonas is a 30 year old teacher,
256
256
00:13:03,390 --> 00:13:06,460
even though the myName and age variables
257
257
00:13:06,460 --> 00:13:09,260
were not defined in the current scope.
258
258
00:13:09,260 --> 00:13:13,950
All the engine did was to get them from the scope chain.
259
259
00:13:13,950 --> 00:13:16,140
And as you might be noticing,
260
260
00:13:16,140 --> 00:13:20,180
we have actually already done this before in our own code.
261
261
00:13:20,180 --> 00:13:23,520
We just didn't really understand what was going on
262
262
00:13:23,520 --> 00:13:25,300
and how it all worked.
263
263
00:13:25,300 --> 00:13:27,940
But now we do know how it works.
264
264
00:13:27,940 --> 00:13:29,233
Amazing, right?
265
265
00:13:30,180 --> 00:13:33,870
Anyway, we still have one more scope left here,
266
266
00:13:33,870 --> 00:13:36,993
and that's the one created by this block here.
267
267
00:13:38,010 --> 00:13:40,880
Remember that starting with ES6,
268
268
00:13:40,880 --> 00:13:45,130
not only functions create scopes, but also blocks.
269
269
00:13:45,130 --> 00:13:49,810
However, these scopes only work for the ES6 variable types.
270
270
00:13:49,810 --> 00:13:52,930
So for let and const variables.
271
271
00:13:52,930 --> 00:13:56,010
That's why the only variable that's in the scope
272
272
00:13:56,010 --> 00:13:58,480
is the decade variable.
273
273
00:13:58,480 --> 00:14:02,650
The millennial variable isn't declared with const or let,
274
274
00:14:02,650 --> 00:14:07,380
and therefore it is not scoped to just this block.
275
275
00:14:07,380 --> 00:14:11,270
Instead, the millennial variable is actually part
276
276
00:14:11,270 --> 00:14:13,580
of the first function scope.
277
277
00:14:13,580 --> 00:14:17,780
So again, for a variable declared with var,
278
278
00:14:17,780 --> 00:14:20,490
block scopes don't apply at all.
279
279
00:14:20,490 --> 00:14:24,160
They are functions scoped, not block scoped.
280
280
00:14:24,160 --> 00:14:26,700
Let and const on the other hand
281
281
00:14:26,700 --> 00:14:30,440
are in fact blocks scoped, okay?
282
282
00:14:30,440 --> 00:14:32,690
This is one of the fundamental things
283
283
00:14:32,690 --> 00:14:36,710
that you need to keep in mind about let, const and var,
284
284
00:14:36,710 --> 00:14:39,760
and about scoping in general.
285
285
00:14:39,760 --> 00:14:43,280
So if you're taking notes and I hope you are taking
286
286
00:14:43,280 --> 00:14:44,970
lots of notes,
287
287
00:14:44,970 --> 00:14:47,543
then this must definitely be in there.
288
288
00:14:48,450 --> 00:14:50,330
Now about a scope chain,
289
289
00:14:50,330 --> 00:14:54,043
if the millennial variable is in the first function scope,
290
290
00:14:54,043 --> 00:14:57,010
then of course the second function scope
291
291
00:14:57,010 --> 00:14:59,130
also has access to it,
292
292
00:14:59,130 --> 00:15:02,550
even if it doesn't really need that variable.
293
293
00:15:02,550 --> 00:15:04,810
Also the scope chain does of course,
294
294
00:15:04,810 --> 00:15:07,500
apply to block scopes as well.
295
295
00:15:07,500 --> 00:15:10,400
And therefore in or if block scope,
296
296
00:15:10,400 --> 00:15:13,120
we get access to all the variables
297
297
00:15:13,120 --> 00:15:15,670
from all its outer scopes.
298
298
00:15:15,670 --> 00:15:17,950
So from the first function scope,
299
299
00:15:17,950 --> 00:15:20,890
and of course from the global scope.
300
300
00:15:20,890 --> 00:15:23,090
That's why I said in the last slide
301
301
00:15:23,090 --> 00:15:25,110
that variables in a global scope
302
302
00:15:25,110 --> 00:15:27,640
are accessible from everywhere.
303
303
00:15:27,640 --> 00:15:29,760
They are, because they are always
304
304
00:15:29,760 --> 00:15:32,290
at the top of the scope chain.
305
305
00:15:32,290 --> 00:15:35,350
In fact, we call variables in the global scope,
306
306
00:15:35,350 --> 00:15:39,200
global variables, very creative, right?
307
307
00:15:39,200 --> 00:15:43,670
But we actually use this term a lot in JavaScript.
308
308
00:15:43,670 --> 00:15:45,630
Now it's important to understand
309
309
00:15:45,630 --> 00:15:47,890
that our purple blocks scope
310
310
00:15:47,890 --> 00:15:50,920
does not get access to any variables
311
311
00:15:50,920 --> 00:15:53,890
from the yellow second function scope.
312
312
00:15:53,890 --> 00:15:56,240
And the same, the other way around.
313
313
00:15:56,240 --> 00:15:58,070
And why is that?
314
314
00:15:58,070 --> 00:16:00,920
Well it's because of lexical scoping
315
315
00:16:00,920 --> 00:16:03,230
as we learned in the last slide.
316
316
00:16:03,230 --> 00:16:05,710
So the way that we can access variables
317
317
00:16:05,710 --> 00:16:08,660
depends on where the scope is placed,
318
318
00:16:08,660 --> 00:16:11,650
so where it is written in the code.
319
319
00:16:11,650 --> 00:16:14,730
In this case, none of these two scopes is written
320
320
00:16:14,730 --> 00:16:17,110
inside of one another.
321
321
00:16:17,110 --> 00:16:20,810
They're both child scopes of the first function.
322
322
00:16:20,810 --> 00:16:24,400
We could even say that they are a sibling scopes.
323
323
00:16:24,400 --> 00:16:27,250
And so by the rules of lexical scoping,
324
324
00:16:27,250 --> 00:16:31,070
they cannot have access to each others variables,
325
325
00:16:31,070 --> 00:16:35,530
simply because one is not written inside the other one.
326
326
00:16:35,530 --> 00:16:37,540
We can also say that the scope chain
327
327
00:16:37,540 --> 00:16:40,803
only works upwards, not sideways.
328
328
00:16:41,860 --> 00:16:45,200
Okay, so this was a lot to take in,
329
329
00:16:45,200 --> 00:16:48,430
but I hope that everything's still keeps making sense
330
330
00:16:48,430 --> 00:16:49,670
at this point.
331
331
00:16:49,670 --> 00:16:51,400
And if not, don't worry,
332
332
00:16:51,400 --> 00:16:54,010
we will see all this working in practice
333
333
00:16:54,010 --> 00:16:56,060
in the next video.
334
334
00:16:56,060 --> 00:16:57,380
But for now, though,
335
335
00:16:57,380 --> 00:17:00,350
there is one more thing that we need to talk about,
336
336
00:17:00,350 --> 00:17:03,010
which is the difference between the scope chain
337
337
00:17:03,010 --> 00:17:04,740
and to call stack.
338
338
00:17:04,740 --> 00:17:08,360
I get a lot of questions about this all the time.
339
339
00:17:08,360 --> 00:17:10,840
And so I decided to talk about
340
340
00:17:10,840 --> 00:17:13,900
how the call stack, execution context,
341
341
00:17:13,900 --> 00:17:16,360
variable environments and scope
342
342
00:17:16,360 --> 00:17:19,310
are all related to one another.
343
343
00:17:19,310 --> 00:17:22,470
So before we move on to the next video.
344
344
00:17:22,470 --> 00:17:23,303
And once more,
345
345
00:17:23,303 --> 00:17:25,703
let's look at some more code here.
346
346
00:17:26,720 --> 00:17:31,550
So we have three functions called first, second and third,
347
347
00:17:31,550 --> 00:17:34,760
in order to make this easier to understand.
348
348
00:17:34,760 --> 00:17:37,430
We start by calling the first function,
349
349
00:17:37,430 --> 00:17:39,730
which then calls the second function,
350
350
00:17:39,730 --> 00:17:42,950
which in turn calls the third function.
351
351
00:17:42,950 --> 00:17:45,130
So from what we learned before,
352
352
00:17:45,130 --> 00:17:50,130
the call stack for this example will look like this, right?
353
353
00:17:50,780 --> 00:17:53,870
One execution context for each function
354
354
00:17:53,870 --> 00:17:57,250
in the exact order in which they were called.
355
355
00:17:57,250 --> 00:17:59,910
They also included the variable environment
356
356
00:17:59,910 --> 00:18:02,570
of each execution context.
357
357
00:18:02,570 --> 00:18:06,010
For now, all this has nothing to do with scopes
358
358
00:18:06,010 --> 00:18:08,490
or the scope chain, all right?
359
359
00:18:08,490 --> 00:18:12,000
All I'm doing is creating one execution context
360
360
00:18:12,000 --> 00:18:14,560
for each function call and filling it
361
361
00:18:14,560 --> 00:18:17,820
with the variables of that function.
362
362
00:18:17,820 --> 00:18:20,410
And you can pause the video here for a moment
363
363
00:18:20,410 --> 00:18:24,003
to understand the content of each variable environment.
364
364
00:18:25,440 --> 00:18:28,120
Okay, and now that you did that
365
365
00:18:28,120 --> 00:18:31,770
and we have all these variable environments in place,
366
366
00:18:31,770 --> 00:18:35,250
we can actually start building the scope chain.
367
367
00:18:35,250 --> 00:18:39,300
As always, we're gonna start with the global scope.
368
368
00:18:39,300 --> 00:18:42,390
And the variables available in the global scope
369
369
00:18:42,390 --> 00:18:46,360
are exactly the ones stored in the variable environment
370
370
00:18:46,360 --> 00:18:49,160
of the global execution context.
371
371
00:18:49,160 --> 00:18:52,020
And given everything we've learned so far,
372
372
00:18:52,020 --> 00:18:54,670
that makes sense, right?
373
373
00:18:54,670 --> 00:18:56,800
And note that in this example,
374
374
00:18:56,800 --> 00:19:00,640
I am actually including functions in each scope
375
375
00:19:00,640 --> 00:19:03,283
unlike we did in the previous slide.
376
376
00:19:04,150 --> 00:19:08,110
Now in the global scope, we also call the first function,
377
377
00:19:08,110 --> 00:19:11,880
which is the reason why we have an execution context for it
378
378
00:19:11,880 --> 00:19:13,530
in the call stack.
379
379
00:19:13,530 --> 00:19:17,260
And this function of course, also gets its own scope,
380
380
00:19:17,260 --> 00:19:20,140
which contains all the variables that are declared
381
381
00:19:20,140 --> 00:19:22,620
inside of the function.
382
382
00:19:22,620 --> 00:19:26,100
And once again, this is exactly the same
383
383
00:19:26,100 --> 00:19:27,900
as the variable environment
384
384
00:19:27,900 --> 00:19:30,820
of the functions execution context.
385
385
00:19:30,820 --> 00:19:32,930
However, that's not all
386
386
00:19:32,930 --> 00:19:36,550
because now we already know about the scope chain.
387
387
00:19:36,550 --> 00:19:40,740
So the first scope also gets access to all the variables
388
388
00:19:40,740 --> 00:19:42,440
from its parent scope,
389
389
00:19:42,440 --> 00:19:44,353
thanks to the scope chain.
390
390
00:19:45,220 --> 00:19:46,860
Now, as we already know,
391
391
00:19:46,860 --> 00:19:49,530
the scope chain is all about the order
392
392
00:19:49,530 --> 00:19:53,080
in which functions are written in the code.
393
393
00:19:53,080 --> 00:19:55,450
But what's really important to note here
394
394
00:19:55,450 --> 00:19:59,400
is that the scope chain has nothing to do with the order
395
395
00:19:59,400 --> 00:20:01,370
in which functions were called.
396
396
00:20:01,370 --> 00:20:05,180
Or in other words, the scope chain has nothing to do
397
397
00:20:05,180 --> 00:20:10,180
with the order of the execution contexts in the call stack.
398
398
00:20:10,280 --> 00:20:13,590
The scope chain does get the variable environments
399
399
00:20:13,590 --> 00:20:17,960
from the execution context as shown by the red arrows here,
400
400
00:20:17,960 --> 00:20:19,520
but that's it.
401
401
00:20:19,520 --> 00:20:22,870
The order of function calls is not relevant
402
402
00:20:22,870 --> 00:20:26,120
to the scope chain at all, all right?
403
403
00:20:26,120 --> 00:20:28,550
Really keep that in mind.
404
404
00:20:28,550 --> 00:20:32,000
Now, moving on to the second function now,
405
405
00:20:32,000 --> 00:20:37,000
once again, its scope is equal to its variable environment.
406
406
00:20:37,280 --> 00:20:41,650
Also it's lexically written within the first function.
407
407
00:20:41,650 --> 00:20:43,000
And so of course,
408
408
00:20:43,000 --> 00:20:47,120
it will have access to all its parent scopes as well.
409
409
00:20:47,120 --> 00:20:50,570
So we can say that the scope chain in a certain scope
410
410
00:20:50,570 --> 00:20:54,640
is equal to adding together all the variable environments
411
411
00:20:54,640 --> 00:20:57,000
of all the parent scopes.
412
412
00:20:57,000 --> 00:20:58,790
And so this is our scope,
413
413
00:20:58,790 --> 00:21:02,230
and the scope chain are built in the JavaScript engine
414
414
00:21:02,230 --> 00:21:03,663
behind the scenes.
415
415
00:21:04,650 --> 00:21:05,650
Okay.
416
416
00:21:05,650 --> 00:21:07,700
Now in the second function,
417
417
00:21:07,700 --> 00:21:11,220
we try to call the third function.
418
418
00:21:11,220 --> 00:21:13,270
But why does that work?
419
419
00:21:13,270 --> 00:21:16,150
Well, it works because the third function
420
420
00:21:16,150 --> 00:21:20,010
is in the scope chain of the second function scope
421
421
00:21:20,010 --> 00:21:23,770
as we can see here in our scope chain diagram.
422
422
00:21:23,770 --> 00:21:28,470
It's a function in the global scope or a global function,
423
423
00:21:28,470 --> 00:21:32,030
and therefore it's accessible everywhere.
424
424
00:21:32,030 --> 00:21:34,740
Of course, this will create a new scope
425
425
00:21:34,740 --> 00:21:38,363
along with the scope chain as we already know.
426
426
00:21:39,230 --> 00:21:43,330
Great, so what happens in this third function?
427
427
00:21:43,330 --> 00:21:47,120
Well, we're trying to act as variables B, C,
428
428
00:21:47,120 --> 00:21:49,750
D and A here.
429
429
00:21:49,750 --> 00:21:53,160
D is no problem because it's right there
430
430
00:21:53,160 --> 00:21:55,330
in the third function scope.
431
431
00:21:55,330 --> 00:21:57,610
So that one is easy.
432
432
00:21:57,610 --> 00:22:01,460
Then variable C is not in a local scope
433
433
00:22:01,460 --> 00:22:05,460
and so JavaScript needs to do a variable lookup.
434
434
00:22:05,460 --> 00:22:07,810
So it looks up in a scope chain
435
435
00:22:07,810 --> 00:22:10,120
looking for variable C,
436
436
00:22:10,120 --> 00:22:12,300
but it's not there.
437
437
00:22:12,300 --> 00:22:14,010
And of course it isn't,
438
438
00:22:14,010 --> 00:22:17,510
because C is defined in the second function,
439
439
00:22:17,510 --> 00:22:20,980
and there is just no way in which the third function
440
440
00:22:20,980 --> 00:22:25,420
can access variables defined in the second function.
441
441
00:22:25,420 --> 00:22:26,540
And that is true,
442
442
00:22:26,540 --> 00:22:30,640
even though it was the second function who called the third.
443
443
00:22:30,640 --> 00:22:32,780
And so here is even more proof
444
444
00:22:32,780 --> 00:22:35,400
that the order in which functions are called
445
445
00:22:35,400 --> 00:22:38,840
does not affect the scope chain at all.
446
446
00:22:38,840 --> 00:22:40,970
And so here as a result,
447
447
00:22:40,970 --> 00:22:42,990
we get the reference error
448
448
00:22:42,990 --> 00:22:46,700
because both C and B cannot be found
449
449
00:22:46,700 --> 00:22:50,063
in the third scope nor in the scope chain.
450
450
00:22:51,030 --> 00:22:51,863
Okay.
451
451
00:22:51,863 --> 00:22:54,810
And with this, I hope I made it crystal clear
452
452
00:22:54,810 --> 00:22:58,540
that execution context, variable environments,
453
453
00:22:58,540 --> 00:23:03,240
the call stack scope and the scope chain are all different,
454
454
00:23:03,240 --> 00:23:06,040
but still very related concepts.
455
455
00:23:06,040 --> 00:23:08,450
And if it's not yet crystal clear,
456
456
00:23:08,450 --> 00:23:12,220
then it's no problem to maybe rewatch this slide,
457
457
00:23:12,220 --> 00:23:15,423
or maybe even this entire lecture a little bit later.
458
458
00:23:16,540 --> 00:23:19,830
And I know that this was quite a long lecture
459
459
00:23:19,830 --> 00:23:23,000
with a ton of stuff to take in.
460
460
00:23:23,000 --> 00:23:25,250
And so here is a handy summary
461
461
00:23:25,250 --> 00:23:28,830
with the main takeaways from this video.
462
462
00:23:28,830 --> 00:23:32,667
So to start, scoping asks the question,
463
463
00:23:32,667 --> 00:23:34,990
"Where do variables live?"
464
464
00:23:34,990 --> 00:23:38,277
Or "Where can we access a certain variable,
465
465
00:23:38,277 --> 00:23:39,860
"and where not?"
466
466
00:23:39,860 --> 00:23:42,623
That's what scoping is all about.
467
467
00:23:43,480 --> 00:23:47,230
Now, there are three types scope in JavaScript.
468
468
00:23:47,230 --> 00:23:50,810
The global scope, scopes defined by functions
469
469
00:23:50,810 --> 00:23:55,570
and scopes defined by blocks, starting in ES6.
470
470
00:23:55,570 --> 00:24:00,200
However, only let and const variables are block scoped.
471
471
00:24:00,200 --> 00:24:04,030
Variables declared with var automatically end up
472
472
00:24:04,030 --> 00:24:05,993
in the closest function scope.
473
473
00:24:06,830 --> 00:24:10,590
Next in JavaScript, we have lexical scoping,
474
474
00:24:10,590 --> 00:24:14,580
which means that the rules of where we can access variables
475
475
00:24:14,580 --> 00:24:17,100
are based on where in the code functions
476
476
00:24:17,100 --> 00:24:18,943
and blocks are written.
477
477
00:24:19,820 --> 00:24:22,580
And now, let the magic begin,
478
478
00:24:22,580 --> 00:24:25,820
because every scope always has access
479
479
00:24:25,820 --> 00:24:29,710
to all the variables from all it's outer scopes.
480
480
00:24:29,710 --> 00:24:32,890
And this is what we call the scope chain.
481
481
00:24:32,890 --> 00:24:36,630
When a certain variable is not in the current scope,
482
482
00:24:36,630 --> 00:24:39,150
the engine looks up in the scope chain
483
483
00:24:39,150 --> 00:24:42,630
until it finds the variable that it's looking for,
484
484
00:24:42,630 --> 00:24:46,240
and this process is called variable lookup.
485
485
00:24:46,240 --> 00:24:48,720
It's important to note that the scope chain
486
486
00:24:48,720 --> 00:24:50,850
is a one way street.
487
487
00:24:50,850 --> 00:24:55,300
So a scope will never ever have access to the variables
488
488
00:24:55,300 --> 00:24:59,620
of an inner scope, only of outer scopes.
489
489
00:24:59,620 --> 00:25:03,490
We can also think of the scope chain in a certain scope
490
490
00:25:03,490 --> 00:25:05,690
as being equal to adding together
491
491
00:25:05,690 --> 00:25:10,280
all the variable environments of all the parent scopes.
492
492
00:25:10,280 --> 00:25:12,780
And finally, we need to keep in mind
493
493
00:25:12,780 --> 00:25:15,350
that the scope chain has nothing to do
494
494
00:25:15,350 --> 00:25:18,970
with the order in which functions were called.
495
495
00:25:18,970 --> 00:25:21,460
So the order of function calls
496
496
00:25:21,460 --> 00:25:24,343
does not affect the scope chain at all.
497
497
00:25:25,260 --> 00:25:27,920
Okay, and now that's actually it.
498
498
00:25:27,920 --> 00:25:32,410
This is in a nutshell, scoping in JavaScript.
499
499
00:25:32,410 --> 00:25:34,363
See you in the next video.
43378
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.