WEBVTT

1
00:00:01.120 --> 00:00:03.650
<v Jonas>So I talked about the JavaScript engine</v>

2
00:00:03.650 --> 00:00:08.040
in the last lecture, but what is that engine actually?

3
00:00:08.040 --> 00:00:10.830
And what is a JavaScript runtime?

4
00:00:10.830 --> 00:00:15.700
Also, how is JavaScript code translated to a machine code?

5
00:00:15.700 --> 00:00:17.470
So that's just some of the topics

6
00:00:17.470 --> 00:00:19.550
that we talked about in the last video.

7
00:00:19.550 --> 00:00:23.483
And so now let's find out how they work in this lecture.

8
00:00:24.900 --> 00:00:27.660
So a JavaScript engine is simply

9
00:00:27.660 --> 00:00:31.740
a computer program that executes JavaScript code.

10
00:00:31.740 --> 00:00:35.080
There are a lot of steps involved in doing that,

11
00:00:35.080 --> 00:00:38.050
but essentially executing JavaScript code

12
00:00:38.050 --> 00:00:40.590
is what an engine does.

13
00:00:40.590 --> 00:00:44.200
Now every browser has its own JavaScript engine

14
00:00:44.200 --> 00:00:49.090
but probably the most well known engine is Google's V-Eight.

15
00:00:49.090 --> 00:00:51.720
The V eight engine powers Google Chrome,

16
00:00:51.720 --> 00:00:55.730
but also Node.js which is that JavaScript runtime

17
00:00:55.730 --> 00:00:58.630
that we talked about in the beginning of the course,

18
00:00:58.630 --> 00:01:02.560
so the one that we can use to build server side applications

19
00:01:02.560 --> 00:01:06.990
with JavaScript, so outside of any browser.

20
00:01:06.990 --> 00:01:09.290
And of course all the other browsers

21
00:01:09.290 --> 00:01:11.510
have their own JavaScript engines

22
00:01:11.510 --> 00:01:15.310
which you can look up online if you're interested.

23
00:01:15.310 --> 00:01:19.430
Anyway, it's quite easy to understand what an engine is

24
00:01:19.430 --> 00:01:22.610
but what's most important is to actually understand

25
00:01:22.610 --> 00:01:25.900
its components and how it works.

26
00:01:25.900 --> 00:01:29.030
So any JavaScript engine always contains

27
00:01:29.030 --> 00:01:32.040
a call stack and a heap.

28
00:01:32.040 --> 00:01:36.250
The call stack is where our code is actually executed

29
00:01:36.250 --> 00:01:39.149
using something called execution contexts.

30
00:01:39.149 --> 00:01:42.880
Then the heap is an unstructured memory pool

31
00:01:42.880 --> 00:01:47.420
which stores all the objects that our application needs.

32
00:01:47.420 --> 00:01:50.770
Alright, so with this look at the engine,

33
00:01:50.770 --> 00:01:54.080
we have answered where our code is executed.

34
00:01:54.080 --> 00:01:55.670
But now the question is

35
00:01:55.670 --> 00:01:58.830
how the code is compiled to machine code

36
00:01:58.830 --> 00:02:02.560
so that it actually can be executed afterwards.

37
00:02:02.560 --> 00:02:04.403
Well, let's find out.

38
00:02:05.600 --> 00:02:07.040
But first we need to make

39
00:02:07.040 --> 00:02:09.780
a quick computer science side note here

40
00:02:09.780 --> 00:02:11.550
and talk about the difference between

41
00:02:11.550 --> 00:02:14.530
compilation and interpretation.

42
00:02:14.530 --> 00:02:15.900
So in the last lecture,

43
00:02:15.900 --> 00:02:18.660
we learned that the computer's processor

44
00:02:18.660 --> 00:02:21.630
only understands zeros and ones

45
00:02:21.630 --> 00:02:25.040
and that's therefore every single computer program

46
00:02:25.040 --> 00:02:29.220
ultimately needs to be converted into this machine code

47
00:02:29.220 --> 00:02:33.860
and this can happen using compilation or interpretation.

48
00:02:33.860 --> 00:02:36.880
So in compilation, the entire source code

49
00:02:36.880 --> 00:02:39.890
is converted into machine code at once.

50
00:02:39.890 --> 00:02:42.520
And this machine code is then written

51
00:02:42.520 --> 00:02:47.440
into a portable file that can be executed on any computer.

52
00:02:47.440 --> 00:02:49.980
So we have two different steps here.

53
00:02:49.980 --> 00:02:52.200
First, the machine code is built

54
00:02:52.200 --> 00:02:56.870
and then it is executed in the CPU so in the processor.

55
00:02:56.870 --> 00:02:58.510
And the execution can happen

56
00:02:58.510 --> 00:03:01.390
way after the compilation of course.

57
00:03:01.390 --> 00:03:04.080
For example, any application that you're using

58
00:03:04.080 --> 00:03:08.210
on your computer right now has been compiled before

59
00:03:08.210 --> 00:03:11.883
and you're now executing it way after it's compilation.

60
00:03:12.740 --> 00:03:15.960
Now, on the other hand in interpretation,

61
00:03:15.960 --> 00:03:19.990
there is an interpreter which runs through the source code

62
00:03:19.990 --> 00:03:22.840
and executes it line by line.

63
00:03:22.840 --> 00:03:27.010
So here we do not have the same two steps as before.

64
00:03:27.010 --> 00:03:32.010
Instead the code is read and executed all at the same time.

65
00:03:32.230 --> 00:03:34.650
Of course the source code still

66
00:03:34.650 --> 00:03:37.430
needs to be converted into machine code,

67
00:03:37.430 --> 00:03:40.810
but it simply happens right before it's executed

68
00:03:40.810 --> 00:03:43.320
and not ahead of time.

69
00:03:43.320 --> 00:03:47.580
Now JavaScript used to be a purely interpreted language

70
00:03:47.580 --> 00:03:50.170
but the problem with interpreted languages

71
00:03:50.170 --> 00:03:54.630
is that they are much, much slower than compiled languages.

72
00:03:54.630 --> 00:03:57.450
This used to be okay for JavaScript,

73
00:03:57.450 --> 00:03:59.770
but now with modern JavaScript

74
00:03:59.770 --> 00:04:02.890
and fully fledged web applications that we built

75
00:04:02.890 --> 00:04:07.890
and use today, low performance is no longer acceptable.

76
00:04:07.930 --> 00:04:11.050
Just imagine you were using Google maps in your browser

77
00:04:11.050 --> 00:04:14.200
and you were dragging the map and each time you dragged

78
00:04:14.200 --> 00:04:17.370
it would take one second for it to move.

79
00:04:17.370 --> 00:04:20.815
That would be completely unacceptable, right?

80
00:04:20.815 --> 00:04:23.060
Now many people still think

81
00:04:23.060 --> 00:04:25.760
that JavaScript is an interpreted language

82
00:04:25.760 --> 00:04:28.410
but that's not really true anymore.

83
00:04:28.410 --> 00:04:31.380
So instead of simple interpretation

84
00:04:31.380 --> 00:04:34.690
modern JavaScript engine now use a mix between

85
00:04:34.690 --> 00:04:37.370
compilation and interpretation

86
00:04:37.370 --> 00:04:41.140
which is called just-in-time compilation.

87
00:04:41.140 --> 00:04:44.130
This approach basically compiles the entire code

88
00:04:44.130 --> 00:04:48.830
into machine code at once and then executes it right away.

89
00:04:48.830 --> 00:04:50.680
So we still have the two steps

90
00:04:50.680 --> 00:04:53.960
of regular ahead of time compilation

91
00:04:53.960 --> 00:04:57.240
but there is no portable file to execute.

92
00:04:57.240 --> 00:05:01.720
And the execution happens immediately after a compilation.

93
00:05:01.720 --> 00:05:04.370
And this is perfect for JavaScript

94
00:05:04.370 --> 00:05:08.350
as it's really a lot faster than just executing code

95
00:05:08.350 --> 00:05:10.250
line by line.

96
00:05:10.250 --> 00:05:13.360
Now I skimmed over some details here

97
00:05:13.360 --> 00:05:16.120
but this is really all you need to know.

98
00:05:16.120 --> 00:05:19.130
Anyway, let's now understand how this works

99
00:05:19.130 --> 00:05:22.023
in the particular case of JavaScript.

100
00:05:23.840 --> 00:05:27.627
So as a piece of JavaScript code enters the engine

101
00:05:27.627 --> 00:05:31.040
the first step is to parse the code

102
00:05:31.040 --> 00:05:34.400
which essentially means to read the code.

103
00:05:34.400 --> 00:05:37.850
During the parsing process, the code is parsed

104
00:05:37.850 --> 00:05:39.850
into a data structure called

105
00:05:39.850 --> 00:05:43.630
the abstract syntax tree or AST.

106
00:05:43.630 --> 00:05:46.670
This works by first splitting up each line of code

107
00:05:46.670 --> 00:05:49.730
into pieces that are meaningful to the language

108
00:05:49.730 --> 00:05:52.490
like the const or function keywords,

109
00:05:52.490 --> 00:05:54.500
and then saving all these pieces

110
00:05:54.500 --> 00:05:57.570
into the tree in a structured way.

111
00:05:57.570 --> 00:06:01.590
This step also checks if there are any syntax errors

112
00:06:01.590 --> 00:06:04.250
and the resulting tree will later be used

113
00:06:04.250 --> 00:06:06.840
to generate the machine code.

114
00:06:06.840 --> 00:06:09.890
Now let's say we have a very simple program.

115
00:06:09.890 --> 00:06:13.800
All it does is to declare a variable like this,

116
00:06:13.800 --> 00:06:15.900
and this is what the AST

117
00:06:15.900 --> 00:06:19.560
for just this one line of code looks like.

118
00:06:19.560 --> 00:06:21.900
So we have a variable declaration

119
00:06:21.900 --> 00:06:23.900
which should be a constant

120
00:06:23.900 --> 00:06:28.500
with the name X and the value of 23.

121
00:06:28.500 --> 00:06:32.050
And besides that there is a lot of other stuff here,

122
00:06:32.050 --> 00:06:33.620
as you can see.

123
00:06:33.620 --> 00:06:35.930
So just imagine what it would look like

124
00:06:35.930 --> 00:06:38.910
for a large real application.

125
00:06:38.910 --> 00:06:41.230
And of course you don't need to know

126
00:06:41.230 --> 00:06:43.520
what an AST looks like.

127
00:06:43.520 --> 00:06:46.990
This is just for curiosity okay.

128
00:06:46.990 --> 00:06:48.850
Now sometimes I get asked

129
00:06:48.850 --> 00:06:53.030
if this tree has anything to do with the DOM tree

130
00:06:53.030 --> 00:06:56.220
and the answer is a very clear no.

131
00:06:56.220 --> 00:07:00.550
So this tree has absolutely nothing to do with the DOM.

132
00:07:00.550 --> 00:07:03.310
It is not related in any way.

133
00:07:03.310 --> 00:07:05.060
It's just a representation

134
00:07:05.060 --> 00:07:08.662
of our entire code inside the engine.

135
00:07:08.662 --> 00:07:11.940
Anyway, the next step is compilation

136
00:07:11.940 --> 00:07:14.610
which takes the generated AST

137
00:07:14.610 --> 00:07:17.330
and compiles it into machine code

138
00:07:17.330 --> 00:07:20.290
just as we learned in the previous slide.

139
00:07:20.290 --> 00:07:24.100
This machine code then gets executed right away

140
00:07:24.100 --> 00:07:27.720
because remember modern JavaScript engine use

141
00:07:27.720 --> 00:07:30.180
just-in-time compilation.

142
00:07:30.180 --> 00:07:32.770
And remember execution happens

143
00:07:32.770 --> 00:07:35.670
in the JavaScript engines call stack

144
00:07:35.670 --> 00:07:39.600
but we will dig deeper into this in the next lecture.

145
00:07:39.600 --> 00:07:42.210
All right, so far so good.

146
00:07:42.210 --> 00:07:46.180
We have our code running so we can finish here, Right?

147
00:07:46.180 --> 00:07:50.120
Well, not so fast because modern JavaScript engines

148
00:07:50.120 --> 00:07:54.110
actually have some pretty clever optimization strategies.

149
00:07:54.110 --> 00:07:57.870
What they do is to create a very unoptimized version

150
00:07:57.870 --> 00:07:59.800
of machine code in the beginning

151
00:07:59.800 --> 00:08:04.400
just so that it can start executing as fast as possible.

152
00:08:04.400 --> 00:08:07.840
Then in the background, this code is being optimized

153
00:08:07.840 --> 00:08:12.840
and recompiled during the already running program execution.

154
00:08:12.900 --> 00:08:15.060
And this can be done most of the times

155
00:08:15.060 --> 00:08:17.170
and after each optimization

156
00:08:17.170 --> 00:08:20.240
the unoptimized code is simply swept

157
00:08:20.240 --> 00:08:22.790
for the new more optimized code

158
00:08:22.790 --> 00:08:26.000
without ever stopping execution of course.

159
00:08:26.000 --> 00:08:29.300
And this process is what makes modern engines

160
00:08:29.300 --> 00:08:32.720
such as the V-Eight so fast

161
00:08:32.720 --> 00:08:36.480
and all this parsing, compilation and optimization

162
00:08:36.480 --> 00:08:40.183
happens in some special threads inside the engine

163
00:08:40.183 --> 00:08:42.730
that we cannot access from our code.

164
00:08:42.730 --> 00:08:45.850
So completely separate from the main thread

165
00:08:45.850 --> 00:08:48.310
that is basically running into call stack

166
00:08:48.310 --> 00:08:50.910
executing our own code.

167
00:08:50.910 --> 00:08:55.250
Now different engines implements in slightly different ways,

168
00:08:55.250 --> 00:08:58.220
but in a nutshell this is what modern

169
00:08:58.220 --> 00:09:02.700
just-in-time compilation looks like for JavaScript.

170
00:09:02.700 --> 00:09:04.720
And the next time someone tells you

171
00:09:04.720 --> 00:09:07.490
JavaScript is an interpreted language,

172
00:09:07.490 --> 00:09:10.550
you just show them this slide so that they can learn

173
00:09:10.550 --> 00:09:12.053
how it really works.

174
00:09:13.280 --> 00:09:16.720
Alright, so we looked at the JavaScript engine

175
00:09:16.720 --> 00:09:20.740
and how it works behind the scenes in quite some detail.

176
00:09:20.740 --> 00:09:23.060
Now to round off this lecture

177
00:09:23.060 --> 00:09:27.050
let's also take a look at what a JavaScript runtime is.

178
00:09:27.050 --> 00:09:29.680
And in particular, the most common one,

179
00:09:29.680 --> 00:09:32.470
which is the browser and by doing this,

180
00:09:32.470 --> 00:09:34.200
we can get the bigger picture

181
00:09:34.200 --> 00:09:38.750
of how all the pieces fit together when we use JavaScript.

182
00:09:38.750 --> 00:09:41.560
And so this is a really important slide.

183
00:09:41.560 --> 00:09:46.480
So we can imagine a JavaScript runtime as a big box

184
00:09:46.480 --> 00:09:48.250
or a big container

185
00:09:48.250 --> 00:09:50.860
which includes all the things that we need

186
00:09:50.860 --> 00:09:55.330
in order to use JavaScript in this case, in the browser.

187
00:09:55.330 --> 00:09:58.197
And to heart of any JavaScript,

188
00:09:58.197 --> 00:10:01.120
runtime is always a JavaScript engine.

189
00:10:01.120 --> 00:10:04.490
So exactly the one we've been talking about.

190
00:10:04.490 --> 00:10:07.570
That's why it makes sense to talk about engines

191
00:10:07.570 --> 00:10:09.690
and runtimes together.

192
00:10:09.690 --> 00:10:12.510
Without an engine there is no runtime

193
00:10:12.510 --> 00:10:15.710
and there is no JavaScript at all.

194
00:10:15.710 --> 00:10:19.500
However the engine alone is not enough.

195
00:10:19.500 --> 00:10:21.470
In order to work properly,

196
00:10:21.470 --> 00:10:24.990
we also need access to the web APIs,

197
00:10:24.990 --> 00:10:28.480
and we talked about web APIs before, remember?

198
00:10:28.480 --> 00:10:31.160
So that's everything related to the DOM

199
00:10:31.160 --> 00:10:36.160
or timers or even the console.log that we use all the time.

200
00:10:36.420 --> 00:10:40.890
So essentially web APIs are functionalities provided

201
00:10:40.890 --> 00:10:42.200
to the engine,

202
00:10:42.200 --> 00:10:44.450
but which are actually not part

203
00:10:44.450 --> 00:10:47.060
of the JavaScript language itself.

204
00:10:47.060 --> 00:10:50.550
JavaScript simply gets access to these APIs

205
00:10:50.550 --> 00:10:53.020
through the global window object.

206
00:10:53.020 --> 00:10:55.720
But it still makes sense that the web APIs

207
00:10:55.720 --> 00:10:58.170
are also part of the runtime,

208
00:10:58.170 --> 00:11:02.460
because again a runtime is just like a box

209
00:11:02.460 --> 00:11:07.050
that contains all the JavaScript related stuff that we need.

210
00:11:07.050 --> 00:11:09.640
Next a typical JavaScript runtime

211
00:11:09.640 --> 00:11:13.300
also includes a so called callback queue.

212
00:11:13.300 --> 00:11:15.840
This is a data structure that contains

213
00:11:15.840 --> 00:11:20.180
all the callback functions that are ready to be executed.

214
00:11:20.180 --> 00:11:23.350
For example we attach event handler functions

215
00:11:23.350 --> 00:11:26.010
to DOM elements like a button

216
00:11:26.010 --> 00:11:28.860
to react to certain events, right?

217
00:11:28.860 --> 00:11:30.700
And these event handler functions

218
00:11:30.700 --> 00:11:34.540
are also called callback functions okay.

219
00:11:34.540 --> 00:11:36.570
So as the event happens,

220
00:11:36.570 --> 00:11:40.900
for example a click, the callback function will be called.

221
00:11:40.900 --> 00:11:44.240
And here is how that actually works behind the scenes.

222
00:11:44.240 --> 00:11:47.900
So the first thing that actually happens after the event

223
00:11:47.900 --> 00:11:50.310
is that the callback function is put

224
00:11:50.310 --> 00:11:52.340
into the callback queue.

225
00:11:52.340 --> 00:11:54.430
Then when the stack is empty

226
00:11:54.430 --> 00:11:57.980
the callback function is passed to the stack

227
00:11:57.980 --> 00:12:00.690
so that it can be executed.

228
00:12:00.690 --> 00:12:04.430
And this happens by something called the event loop.

229
00:12:04.430 --> 00:12:07.430
So basically the event loop takes callback functions

230
00:12:07.430 --> 00:12:08.960
from the callback queue

231
00:12:08.960 --> 00:12:11.150
and puts them in the call stack

232
00:12:11.150 --> 00:12:13.850
so that they can be executed.

233
00:12:13.850 --> 00:12:16.570
And remember how I said in the last lecture

234
00:12:16.570 --> 00:12:17.550
that the event loop

235
00:12:17.550 --> 00:12:21.000
is how JavaScript's nonblocking concurrency model

236
00:12:21.000 --> 00:12:22.740
is implemented?

237
00:12:22.740 --> 00:12:26.830
Well, here is an overview of how that works.

238
00:12:26.830 --> 00:12:31.380
Now we will go over why this makes JavaScript nonblocking

239
00:12:31.380 --> 00:12:33.900
in a special lecture about the event loop

240
00:12:33.900 --> 00:12:35.200
later in the course,

241
00:12:35.200 --> 00:12:37.760
because this is really a fundamental piece

242
00:12:37.760 --> 00:12:39.770
of JavaScript development

243
00:12:39.770 --> 00:12:43.083
that every developer needs to understand deeply.

244
00:12:44.180 --> 00:12:48.560
Alright, so as they already said the focus in this course

245
00:12:48.560 --> 00:12:51.100
is on JavaScript in the browser

246
00:12:51.100 --> 00:12:55.660
and that's why we analyzed the browser JavaScript runtime.

247
00:12:55.660 --> 00:12:58.120
However, it's also important to remember

248
00:12:58.120 --> 00:13:01.630
that JavaScript can exist outside of browsers,

249
00:13:01.630 --> 00:13:03.830
for example, in Node.js.

250
00:13:03.830 --> 00:13:07.440
And so here is what the node JS JavaScript runtime

251
00:13:07.440 --> 00:13:08.880
looks like.

252
00:13:08.880 --> 00:13:12.300
It's pretty similar, but since we don't have a browser

253
00:13:12.300 --> 00:13:15.360
of course, we can't have the web APIs

254
00:13:15.360 --> 00:13:18.450
because it's the browser who provides these.

255
00:13:18.450 --> 00:13:21.970
Instead we have multiple C ++ bindings

256
00:13:21.970 --> 00:13:24.570
and a so called thread pool.

257
00:13:24.570 --> 00:13:27.110
Now details don't matter here at all.

258
00:13:27.110 --> 00:13:28.470
I just want you to know

259
00:13:28.470 --> 00:13:32.200
that different JavaScript runtimes do exist.

260
00:13:32.200 --> 00:13:35.460
Alright cool, that's all I had to tell you

261
00:13:35.460 --> 00:13:39.010
about JavaScript engines and runtimes.

262
00:13:39.010 --> 00:13:43.260
In our next lecture we will learn how JavaScript is executed

263
00:13:43.260 --> 00:13:44.533
in the call stack.

