Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
1
00:00:01,530 --> 00:00:03,490
The next topic we need to talk about
2
2
00:00:03,490 --> 00:00:07,570
is a very misunderstood concept in JavaScript
3
3
00:00:07,570 --> 00:00:09,313
and that is hoisting.
4
4
00:00:11,550 --> 00:00:14,380
So we learned that an execution context
5
5
00:00:14,380 --> 00:00:16,810
always contains three parts.
6
6
00:00:16,810 --> 00:00:18,800
A variable environment,
7
7
00:00:18,800 --> 00:00:21,530
the scope chain in the current context,
8
8
00:00:21,530 --> 00:00:23,500
and the disk keyword.
9
9
00:00:23,500 --> 00:00:26,110
We already learned about the scope chain
10
10
00:00:26,110 --> 00:00:28,800
and so now it's time to take a closer look
11
11
00:00:28,800 --> 00:00:31,090
at the variable environment
12
12
00:00:31,090 --> 00:00:33,750
and in particular at how variables
13
13
00:00:33,750 --> 00:00:37,320
are actually created in JavaScript.
14
14
00:00:37,320 --> 00:00:38,810
So in JavaScript
15
15
00:00:38,810 --> 00:00:41,630
we have a mechanism called hoisting.
16
16
00:00:41,630 --> 00:00:43,600
And hoisting basically make
17
17
00:00:43,600 --> 00:00:46,450
some types of variables accessible,
18
18
00:00:46,450 --> 00:00:49,570
or let's say usable in the code
19
19
00:00:49,570 --> 00:00:52,963
before they are actually declared in the code.
20
20
00:00:53,830 --> 00:00:56,520
Now, many people simply define hoisting
21
21
00:00:56,520 --> 00:01:00,030
by saying that variables are magically lifted
22
22
00:01:00,030 --> 00:01:03,530
or moved to the top of their scope
23
23
00:01:03,530 --> 00:01:06,640
for example, to the top of a function.
24
24
00:01:06,640 --> 00:01:08,790
And that is actually what hoisting
25
25
00:01:08,790 --> 00:01:11,020
looks like on the surface.
26
26
00:01:11,020 --> 00:01:12,520
But behind the scenes
27
27
00:01:12,520 --> 00:01:15,830
that's in fact not what happens.
28
28
00:01:15,830 --> 00:01:17,970
Instead, behind the scenes
29
29
00:01:17,970 --> 00:01:19,780
the code is basically scanned
30
30
00:01:19,780 --> 00:01:24,420
for variable declarations before it is executed.
31
31
00:01:24,420 --> 00:01:26,430
So this happens during the so-called
32
32
00:01:26,430 --> 00:01:29,660
creation phase of the execution context
33
33
00:01:29,660 --> 00:01:32,010
that we talked about before.
34
34
00:01:32,010 --> 00:01:35,530
Then for each variable that is found in the code,
35
35
00:01:35,530 --> 00:01:37,630
a new property is created
36
36
00:01:37,630 --> 00:01:40,330
in a variable environment object.
37
37
00:01:40,330 --> 00:01:43,470
And that's how hoisting really works.
38
38
00:01:43,470 --> 00:01:46,150
Now, hoisting does not work the same
39
39
00:01:46,150 --> 00:01:48,160
for all variable types.
40
40
00:01:48,160 --> 00:01:50,890
And so let's analyze the way hosting works
41
41
00:01:50,890 --> 00:01:53,100
for function declarations,
42
42
00:01:53,100 --> 00:01:55,620
variables defined with var
43
43
00:01:55,620 --> 00:01:58,670
variables defined with let or const
44
44
00:01:58,670 --> 00:02:00,700
and function expressions,
45
45
00:02:00,700 --> 00:02:03,410
and also arrow functions.
46
46
00:02:03,410 --> 00:02:07,060
So function declarations are actually hoisted
47
47
00:02:07,060 --> 00:02:10,360
and the initial value in the variable environment
48
48
00:02:10,360 --> 00:02:13,550
is set to the actual function.
49
49
00:02:13,550 --> 00:02:15,970
So in practice, what this means
50
50
00:02:15,970 --> 00:02:18,490
is that we can use function declarations
51
51
00:02:18,490 --> 00:02:22,430
before they are actually declared in the code,
52
52
00:02:22,430 --> 00:02:24,340
again, because they are stored
53
53
00:02:24,340 --> 00:02:26,650
in the variable environment object,
54
54
00:02:26,650 --> 00:02:30,360
even before the code starts executing.
55
55
00:02:30,360 --> 00:02:32,070
And I actually told you before
56
56
00:02:32,070 --> 00:02:35,030
that function declarations work this way,
57
57
00:02:35,030 --> 00:02:37,290
but now you understand why.
58
58
00:02:37,290 --> 00:02:39,900
It is because of hoisting.
59
59
00:02:39,900 --> 00:02:43,100
And just to make this table a bit more complete
60
60
00:02:43,100 --> 00:02:46,450
so that it serves as a nice overview for you,
61
61
00:02:46,450 --> 00:02:49,280
I also show here that function declarations
62
62
00:02:49,280 --> 00:02:52,800
are block scoped as we learned before.
63
63
00:02:52,800 --> 00:02:55,360
Just keep in mind that this is only true
64
64
00:02:55,360 --> 00:02:57,220
for strict mode.
65
65
00:02:57,220 --> 00:02:59,430
So if you're using a sloppy mode,
66
66
00:02:59,430 --> 00:03:00,800
which you shouldn't ,
67
67
00:03:00,800 --> 00:03:04,070
then functions are functioned sculpt.
68
68
00:03:04,070 --> 00:03:07,310
Next, variables declared with var
69
69
00:03:07,310 --> 00:03:10,370
are also hoisted, but hoisting works
70
70
00:03:10,370 --> 00:03:12,430
in a different way here.
71
71
00:03:12,430 --> 00:03:14,010
So unlike functions,
72
72
00:03:14,010 --> 00:03:16,860
when we try to access a var variable
73
73
00:03:16,860 --> 00:03:19,220
before it's declared in a code,
74
74
00:03:19,220 --> 00:03:21,760
we don't get the declared value
75
75
00:03:21,760 --> 00:03:23,980
but we get undefined.
76
76
00:03:23,980 --> 00:03:28,110
And this is a really weird behavior for beginners.
77
77
00:03:28,110 --> 00:03:31,080
You might expect that you simply get an error
78
78
00:03:31,080 --> 00:03:33,980
when using a variable before declaring it
79
79
00:03:33,980 --> 00:03:36,140
or to get the actual value.
80
80
00:03:36,140 --> 00:03:38,610
But not to get undefined
81
81
00:03:38,610 --> 00:03:42,300
because getting undefined is just really weird
82
82
00:03:42,300 --> 00:03:45,640
and it's not really useful either, right?
83
83
00:03:45,640 --> 00:03:47,500
And actually this behavior
84
84
00:03:47,500 --> 00:03:51,130
is a common source of bugs in JavaScript.
85
85
00:03:51,130 --> 00:03:53,230
So this is one of the main reasons
86
86
00:03:53,230 --> 00:03:55,060
why in modern JavaScript
87
87
00:03:55,060 --> 00:03:58,250
we almost never use var.
88
88
00:03:58,250 --> 00:03:59,550
Now on the other hand,
89
89
00:03:59,550 --> 00:04:03,680
let and const variables are not hoisted.
90
90
00:04:03,680 --> 00:04:07,060
I mean, technically they are actually hoisted
91
91
00:04:07,060 --> 00:04:11,120
but their value is basically set to an initialized.
92
92
00:04:11,120 --> 00:04:14,420
So there is no value to work with at all.
93
93
00:04:14,420 --> 00:04:17,410
And so in practice, it is as if hoisting
94
94
00:04:17,410 --> 00:04:19,950
was not happening at all.
95
95
00:04:19,950 --> 00:04:22,280
Instead, we say that these variables
96
96
00:04:22,280 --> 00:04:27,280
are placed in a so-called Temporal Dead Zone or TDZ
97
97
00:04:27,540 --> 00:04:30,700
which makes it so that we can't access the variables
98
98
00:04:30,700 --> 00:04:32,800
between the beginning of the scope
99
99
00:04:32,800 --> 00:04:36,600
and to place where the variables are declared.
100
100
00:04:36,600 --> 00:04:38,010
So as a consequence,
101
101
00:04:38,010 --> 00:04:41,380
if we attempt to use a let or const variable
102
102
00:04:41,380 --> 00:04:45,050
before it's declared, we get an error.
103
103
00:04:45,050 --> 00:04:49,620
Also keep in mind that let and const are block scoped.
104
104
00:04:49,620 --> 00:04:51,620
So they exist only in the block
105
105
00:04:51,620 --> 00:04:53,700
in which they were created.
106
106
00:04:53,700 --> 00:04:55,850
And all these factors together
107
107
00:04:55,850 --> 00:04:58,700
is basically the reason why let and const
108
108
00:04:58,700 --> 00:05:01,420
were first introduced into the language,
109
109
00:05:01,420 --> 00:05:04,130
and why we use them now instead of var
110
110
00:05:04,130 --> 00:05:06,450
in modern JavaScript.
111
111
00:05:06,450 --> 00:05:07,283
Okay.
112
112
00:05:07,283 --> 00:05:09,960
But now what about function expressions
113
113
00:05:09,960 --> 00:05:11,940
and arrow functions?
114
114
00:05:11,940 --> 00:05:14,710
How does hoisting work for this?
115
115
00:05:14,710 --> 00:05:17,270
Well, it depends if they were created
116
116
00:05:17,270 --> 00:05:20,540
using var or const or let.
117
117
00:05:20,540 --> 00:05:23,020
Because keep in mind that these functions
118
118
00:05:23,020 --> 00:05:24,790
are simply variables.
119
119
00:05:24,790 --> 00:05:27,460
And so they behave the exact same way
120
120
00:05:27,460 --> 00:05:30,940
as variables in regard to hoisting.
121
121
00:05:30,940 --> 00:05:33,220
This means that a function expression
122
122
00:05:33,220 --> 00:05:36,420
or arrow function created with var
123
123
00:05:36,420 --> 00:05:38,600
is hoisted to undefined.
124
124
00:05:38,600 --> 00:05:41,660
But if created with let or const,
125
125
00:05:41,660 --> 00:05:45,130
it's not usable before it's declared in a code
126
126
00:05:45,130 --> 00:05:48,150
because of the Temporal Dead Zone
127
127
00:05:48,150 --> 00:05:52,620
so again, just like normal variables, right?
128
128
00:05:52,620 --> 00:05:56,250
And this is actually the reason why I told you earlier
129
129
00:05:56,250 --> 00:05:58,840
that we cannot use function expressions
130
130
00:05:58,840 --> 00:06:01,450
before we write them in the code,
131
131
00:06:01,450 --> 00:06:03,823
unlike function declarations.
132
132
00:06:05,480 --> 00:06:06,380
Okay.
133
133
00:06:06,380 --> 00:06:08,320
But now before finishing,
134
134
00:06:08,320 --> 00:06:10,550
let's take a more detailed look
135
135
00:06:10,550 --> 00:06:14,020
at this mysterious Temporal Dead Zone.
136
136
00:06:14,020 --> 00:06:16,090
So in this example code
137
137
00:06:16,090 --> 00:06:19,620
we're gonna look at the job variable.
138
138
00:06:19,620 --> 00:06:24,210
It is a const so it's scoped only to this if block
139
139
00:06:24,210 --> 00:06:25,760
and it's gonna be accessible
140
140
00:06:25,760 --> 00:06:29,330
starting from the line where it's defined.
141
141
00:06:29,330 --> 00:06:30,490
Why?
142
142
00:06:30,490 --> 00:06:33,920
Well, because there is this Temporal Dead Zone
143
143
00:06:33,920 --> 00:06:36,130
for the job variable.
144
144
00:06:36,130 --> 00:06:38,230
It's basically the region of the scope
145
145
00:06:38,230 --> 00:06:40,540
in which the variable is defined,
146
146
00:06:40,540 --> 00:06:43,260
but can't be used in any way.
147
147
00:06:43,260 --> 00:06:47,650
So it is as if the variable didn't even exist.
148
148
00:06:47,650 --> 00:06:50,510
Now, if we still tried to access the variable
149
149
00:06:50,510 --> 00:06:53,390
while in the TDZ like we actually
150
150
00:06:53,390 --> 00:06:56,580
do in the first line of this if block,
151
151
00:06:56,580 --> 00:06:58,810
then we get a reference error
152
152
00:06:58,810 --> 00:07:01,170
telling us that we can't access job
153
153
00:07:01,170 --> 00:07:03,320
before initialization.
154
154
00:07:03,320 --> 00:07:04,970
So exactly as we learned
155
155
00:07:04,970 --> 00:07:06,823
in the last slide, right?
156
156
00:07:07,720 --> 00:07:10,773
However, if we tried to access a variable
157
157
00:07:10,773 --> 00:07:13,710
that was actually never even created,
158
158
00:07:13,710 --> 00:07:15,470
like in the last line here
159
159
00:07:15,470 --> 00:07:17,670
where we want to log x,
160
160
00:07:17,670 --> 00:07:20,090
then we get a different error message
161
161
00:07:20,090 --> 00:07:23,720
saying that x is not defined at all.
162
162
00:07:23,720 --> 00:07:25,820
What this means is that job is
163
163
00:07:25,820 --> 00:07:28,430
in fact in the Temporal Dead Zone
164
164
00:07:28,430 --> 00:07:30,550
where it is still initialized,
165
165
00:07:30,550 --> 00:07:32,370
but the engine knows that it will
166
166
00:07:32,370 --> 00:07:34,900
eventually be initialized
167
167
00:07:34,900 --> 00:07:37,610
because it already read the code before
168
168
00:07:37,610 --> 00:07:41,010
and set the job variable in the variable environment
169
169
00:07:41,010 --> 00:07:43,200
to uninitialized.
170
170
00:07:43,200 --> 00:07:45,530
Then when the execution reaches the line
171
171
00:07:45,530 --> 00:07:47,690
where the variable is declared,
172
172
00:07:47,690 --> 00:07:50,300
it is removed from the Temporal Dead Zone
173
173
00:07:50,300 --> 00:07:53,000
and it's then safe to use.
174
174
00:07:53,000 --> 00:07:56,130
So to recap, basically each and every
175
175
00:07:56,130 --> 00:07:58,540
let and const variable get their own
176
176
00:07:58,540 --> 00:08:00,570
Temporal Dead Zone that starts
177
177
00:08:00,570 --> 00:08:02,250
at the beginning of the scope
178
178
00:08:02,250 --> 00:08:05,180
until the line where it is defined.
179
179
00:08:05,180 --> 00:08:07,660
And the variable is only safe to use
180
180
00:08:07,660 --> 00:08:09,990
after the TDZ,
181
181
00:08:09,990 --> 00:08:12,740
so the Temporal Dead Zone.
182
182
00:08:12,740 --> 00:08:15,920
Alright, now what is actually the need
183
183
00:08:15,920 --> 00:08:19,480
for JavaScript to have a Temporal Dead Zone?
184
184
00:08:19,480 --> 00:08:22,320
Well, the main reason that the TDZ
185
185
00:08:22,320 --> 00:08:25,340
was introduced in ES6 is that
186
186
00:08:25,340 --> 00:08:27,490
the behavior I described before
187
187
00:08:27,490 --> 00:08:31,660
makes it way easier to avoid and catch errors.
188
188
00:08:31,660 --> 00:08:35,030
Because using a variable that is set to undefined
189
189
00:08:35,030 --> 00:08:37,150
before it's actually declared
190
190
00:08:37,150 --> 00:08:39,150
can cause serious bugs
191
191
00:08:39,150 --> 00:08:41,320
which might be hard to find.
192
192
00:08:41,320 --> 00:08:43,050
And I will show you a small example
193
193
00:08:43,050 --> 00:08:44,253
in the next lecture.
194
194
00:08:45,290 --> 00:08:48,430
So accessing variables before declaration
195
195
00:08:48,430 --> 00:08:51,650
is bad practice and should be avoided.
196
196
00:08:51,650 --> 00:08:53,530
And the best way to avoid it
197
197
00:08:53,530 --> 00:08:55,360
is by simply getting an error
198
198
00:08:55,360 --> 00:08:57,410
when we attempt to do so.
199
199
00:08:57,410 --> 00:09:00,653
And that's exactly what a Temporal Dead Zone does.
200
200
00:09:01,610 --> 00:09:05,880
A second and smaller reason why the TDZ exists
201
201
00:09:05,880 --> 00:09:07,570
is to make const variables
202
202
00:09:07,570 --> 00:09:10,770
actually work the way they are supposed to.
203
203
00:09:10,770 --> 00:09:14,560
So as you know, we can't reassign const variables.
204
204
00:09:14,560 --> 00:09:16,270
So it will not be possible
205
205
00:09:16,270 --> 00:09:18,350
to set them to undefined first
206
206
00:09:18,350 --> 00:09:21,700
and then assign their real value later.
207
207
00:09:21,700 --> 00:09:24,340
Const should never be reassigned.
208
208
00:09:24,340 --> 00:09:27,200
And so it's only assigned when execution
209
209
00:09:27,200 --> 00:09:30,090
actually reaches the declaration.
210
210
00:09:30,090 --> 00:09:31,690
And that makes it impossible
211
211
00:09:31,690 --> 00:09:34,160
to use the variable before.
212
212
00:09:34,160 --> 00:09:36,083
Okay? Makes sense?
213
213
00:09:37,000 --> 00:09:40,530
Now, if hoisting creates so many problems,
214
214
00:09:40,530 --> 00:09:43,720
why does it exist in the first place?
215
215
00:09:43,720 --> 00:09:45,720
I get this question all the time.
216
216
00:09:45,720 --> 00:09:48,660
And so let's quickly talk about that here.
217
217
00:09:48,660 --> 00:09:51,460
So the creator of JavaScript basically
218
218
00:09:51,460 --> 00:09:53,050
implemented hoisting
219
219
00:09:53,050 --> 00:09:55,480
so that we can use function declarations
220
220
00:09:55,480 --> 00:09:57,330
before we use them.
221
221
00:09:57,330 --> 00:09:58,930
Because this is essential
222
222
00:09:58,930 --> 00:10:01,020
for some programming techniques,
223
223
00:10:01,020 --> 00:10:03,570
such as mutual recursion.
224
224
00:10:03,570 --> 00:10:06,100
Some people also think that it makes code
225
225
00:10:06,100 --> 00:10:08,310
a lot more readable.
226
226
00:10:08,310 --> 00:10:12,220
Now, the fact that it also works for var declarations
227
227
00:10:12,220 --> 00:10:14,700
is because that was the only way hoisting
228
228
00:10:14,700 --> 00:10:17,390
could be implemented at the time.
229
229
00:10:17,390 --> 00:10:20,090
So the hoisting of var variables
230
230
00:10:20,090 --> 00:10:22,140
is basically just a byproduct
231
231
00:10:22,140 --> 00:10:24,290
of hoisting functions.
232
232
00:10:24,290 --> 00:10:27,000
And it probably seemed like a good idea
233
233
00:10:27,000 --> 00:10:29,860
to simply set variables to undefined,
234
234
00:10:29,860 --> 00:10:33,460
which in hindsight is not really that great.
235
235
00:10:33,460 --> 00:10:35,780
But we need to remember that JavaScript
236
236
00:10:35,780 --> 00:10:38,160
was never intended to become the huge
237
237
00:10:38,160 --> 00:10:41,090
programming language that it is today.
238
238
00:10:41,090 --> 00:10:43,350
Also, we can't remove this feature
239
239
00:10:43,350 --> 00:10:44,850
from the language now.
240
240
00:10:44,850 --> 00:10:48,323
And so we just use let and const to work around this.
241
241
00:10:49,610 --> 00:10:51,580
Alright, great.
242
242
00:10:51,580 --> 00:10:53,780
And with all that being said,
243
243
00:10:53,780 --> 00:10:57,573
let's now work on some practical hoisting examples.
19893
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.