WEBVTT

1
00:00:00.080 --> 00:00:02.560
<v Speaker 1>If I asked you to add point one and a

2
00:00:02.600 --> 00:00:05.719
<v Speaker 1>point two, you would probably just confidently say point three, right.

3
00:00:05.719 --> 00:00:07.160
<v Speaker 2>I mean, it's basic maths.

4
00:00:06.839 --> 00:00:09.599
<v Speaker 1>Exactly, it's basic math. But if you ask JavaScript to

5
00:00:09.640 --> 00:00:13.359
<v Speaker 1>do that exact same calculation, it spits out zero point

6
00:00:13.400 --> 00:00:16.960
<v Speaker 1>three zero zero zero zero zero zero zero zero zero

7
00:00:17.120 --> 00:00:17.679
<v Speaker 1>zero zero.

8
00:00:17.879 --> 00:00:20.120
<v Speaker 2>Yeah, which is usually the moment a new developer just

9
00:00:20.160 --> 00:00:21.920
<v Speaker 2>stares at their screen in total disbelief.

10
00:00:21.960 --> 00:00:24.760
<v Speaker 1>Oh absolutely, So, today we are taking a deep dive

11
00:00:24.839 --> 00:00:27.559
<v Speaker 1>into why one of the world's most you know, widely

12
00:00:27.640 --> 00:00:32.119
<v Speaker 1>used programming language fundamentally struggles with basic math, and more importantly,

13
00:00:32.399 --> 00:00:36.560
<v Speaker 1>how understanding its hidden quarks can actually make you a master.

14
00:00:36.320 --> 00:00:40.280
<v Speaker 2>Coder because it is a language built on honestly brilliant flexibility.

15
00:00:40.479 --> 00:00:43.560
<v Speaker 2>But that flexibility comes with this massive shadow, like if

16
00:00:43.560 --> 00:00:45.960
<v Speaker 2>you don't know the mechanical rules operating under the hood.

17
00:00:46.240 --> 00:00:48.799
<v Speaker 2>That shadow is exactly where all your worst bugs are

18
00:00:48.799 --> 00:00:49.320
<v Speaker 2>going to hide.

19
00:00:49.320 --> 00:00:51.560
<v Speaker 1>And that is exactly what we are waiting into today.

20
00:00:51.719 --> 00:00:54.359
<v Speaker 1>Welcome to the deep dive. Our mission today is to

21
00:00:54.359 --> 00:00:57.600
<v Speaker 1>move beyond just like memorizing JavaScript syntax, we want to

22
00:00:57.640 --> 00:01:01.079
<v Speaker 1>master its pragmatics. We're using a phenomenal source text today,

23
00:01:01.119 --> 00:01:04.920
<v Speaker 1>Effective JavaScript by David Herman, and the whole goal here

24
00:01:04.959 --> 00:01:07.159
<v Speaker 1>is to pull back the curtain. We want to turn

25
00:01:07.319 --> 00:01:12.400
<v Speaker 1>those frustrating you know, keyboard smashing gotchas into real aha moments,

26
00:01:12.640 --> 00:01:14.799
<v Speaker 1>so you can write highly predictable code.

27
00:01:14.920 --> 00:01:18.159
<v Speaker 2>And you really need that predictability because JavaScript is everywhere.

28
00:01:18.400 --> 00:01:22.280
<v Speaker 2>You're probably dealing with constant information overload, just trying to

29
00:01:22.359 --> 00:01:23.640
<v Speaker 2>keep up with the newest framework.

30
00:01:23.760 --> 00:01:25.239
<v Speaker 1>Well there's a new one every week, right.

31
00:01:25.480 --> 00:01:28.799
<v Speaker 2>But the libraries change every year, the core mechanics do not.

32
00:01:29.480 --> 00:01:33.400
<v Speaker 2>So by taking a structured, respectful pace today, we really

33
00:01:33.480 --> 00:01:35.519
<v Speaker 2>want to cut through all that noise and deliver the

34
00:01:35.640 --> 00:01:38.480
<v Speaker 2>underlying reasons why JavaScript behaves the way it does.

35
00:01:38.640 --> 00:01:40.920
<v Speaker 1>Okay, let's unpack this. We have to start at the

36
00:01:40.959 --> 00:01:45.519
<v Speaker 1>absolute foundation. If you don't understand how a language interprets

37
00:01:45.560 --> 00:01:48.280
<v Speaker 1>basic data, I mean, nothing else built on top of

38
00:01:48.280 --> 00:01:50.159
<v Speaker 1>it will make any sense. Yeah, the data is everything,

39
00:01:50.280 --> 00:01:53.040
<v Speaker 1>and our source material drops a major bombshell right in

40
00:01:53.120 --> 00:01:57.040
<v Speaker 1>chapter one. JavaScript has no true integers.

41
00:01:56.560 --> 00:01:59.200
<v Speaker 2>None, zero, none, whatsoever.

42
00:01:59.319 --> 00:02:01.400
<v Speaker 1>That is why to me, it is.

43
00:02:01.719 --> 00:02:04.840
<v Speaker 2>Every single time you type a one or a forty two,

44
00:02:05.079 --> 00:02:08.479
<v Speaker 2>or like a negative five, JavaScript is actually storing it

45
00:02:08.520 --> 00:02:12.280
<v Speaker 2>as a sixty four bit double precision floating point number. Okay, wait,

46
00:02:12.719 --> 00:02:16.439
<v Speaker 2>it uses the the IE seven fifty four standard, which

47
00:02:16.479 --> 00:02:18.919
<v Speaker 2>is basically just a fancy way of saying it stores

48
00:02:19.000 --> 00:02:21.319
<v Speaker 2>everything as a decimal in binary format.

49
00:02:21.400 --> 00:02:24.479
<v Speaker 1>So even a perfectly whole number like a solid integer,

50
00:02:24.960 --> 00:02:27.520
<v Speaker 1>is secretly carrying decimal point baggage.

51
00:02:27.599 --> 00:02:30.879
<v Speaker 2>Yes, exactly, and this is exactly why your point one

52
00:02:30.960 --> 00:02:32.719
<v Speaker 2>plus point two equation fails.

53
00:02:32.840 --> 00:02:34.000
<v Speaker 1>Okay, break that down for me.

54
00:02:34.240 --> 00:02:36.159
<v Speaker 2>Think about how we do math in base ten like

55
00:02:36.240 --> 00:02:38.840
<v Speaker 2>normal decimals. If you try to write the fraction one

56
00:02:38.960 --> 00:02:41.560
<v Speaker 2>third is decimal, you literally can't do it perfectly. You

57
00:02:41.599 --> 00:02:43.240
<v Speaker 2>get point three three three repeating forever.

58
00:02:43.400 --> 00:02:45.080
<v Speaker 1>Right. Eventually you just have to chop it off and

59
00:02:45.120 --> 00:02:46.039
<v Speaker 1>you lose a tiny bit of.

60
00:02:46.039 --> 00:02:50.120
<v Speaker 2>Precision exactly because base ten can't cleanly divide by three. Well, binary,

61
00:02:50.159 --> 00:02:52.879
<v Speaker 2>which is base two, has that exact same problem with

62
00:02:52.919 --> 00:02:56.159
<v Speaker 2>fractions like one tenth. It cannot cleanly represent point one.

63
00:02:56.280 --> 00:02:59.000
<v Speaker 1>Oh so it creates a repeating decimal in binary.

64
00:02:59.080 --> 00:03:02.439
<v Speaker 2>Yes, it creates repeating binary decimal, and the computer has

65
00:03:02.439 --> 00:03:04.599
<v Speaker 2>to chop it off at sixty four bits, which leaves

66
00:03:04.599 --> 00:03:06.960
<v Speaker 2>this microscopic fraction of a remainder. Oh wow, So when

67
00:03:07.000 --> 00:03:10.439
<v Speaker 2>you add two of those imprecise binary decimals together, that

68
00:03:10.560 --> 00:03:14.199
<v Speaker 2>tiny little remainder overflows into your visible result, and boom,

69
00:03:14.240 --> 00:03:18.479
<v Speaker 2>you get that bizarre point three zero zero zero zero

70
00:03:18.639 --> 00:03:21.439
<v Speaker 2>zero zero zero zero zero zero zero zero.

71
00:03:21.439 --> 00:03:23.599
<v Speaker 1>Four that makes so much sense. It's not a bug

72
00:03:23.639 --> 00:03:26.520
<v Speaker 1>at all. It's just a fundamental limitation of trying to

73
00:03:26.520 --> 00:03:29.159
<v Speaker 1>map base ten fractions onto base two hardware.

74
00:03:29.280 --> 00:03:29.759
<v Speaker 2>Exactly.

75
00:03:30.319 --> 00:03:33.080
<v Speaker 1>Well, wait, let me logic through something here. If every

76
00:03:33.120 --> 00:03:36.479
<v Speaker 1>single number is a floating point, decimal bitwise operator shouldn't

77
00:03:36.479 --> 00:03:39.000
<v Speaker 1>even work. I mean, you can't flip binary bits on

78
00:03:39.000 --> 00:03:42.919
<v Speaker 1>a floating decimal point. Right, bitwise math inherently relies on

79
00:03:43.080 --> 00:03:45.319
<v Speaker 1>strict thirty two bit integers.

80
00:03:45.599 --> 00:03:48.080
<v Speaker 2>You are entirely correct. Technically, you shouldn't be able to

81
00:03:48.120 --> 00:03:51.319
<v Speaker 2>do it. But JavaScript does something incredibly sneaky behind your

82
00:03:51.319 --> 00:03:53.639
<v Speaker 2>back to make it work anyway, of course it does. Yeah,

83
00:03:53.680 --> 00:03:55.919
<v Speaker 2>So when you use a bitwise operator, the engine silently

84
00:03:55.960 --> 00:03:58.360
<v Speaker 2>takes your sixty four big float, It actually converts it

85
00:03:58.400 --> 00:04:01.120
<v Speaker 2>into a thirty two bit interature, performs a bitwise math

86
00:04:01.159 --> 00:04:03.919
<v Speaker 2>on it, and then secretly converts the result back into

87
00:04:03.960 --> 00:04:05.960
<v Speaker 2>a standard sixty four bit floating point.

88
00:04:06.039 --> 00:04:06.800
<v Speaker 1>Are you serious?

89
00:04:07.000 --> 00:04:09.639
<v Speaker 2>Yeah? It all happens completely invisibly and just a fraction

90
00:04:09.719 --> 00:04:10.919
<v Speaker 2>of a millisecond.

91
00:04:10.719 --> 00:04:14.400
<v Speaker 1>Talk about doing things behind my back. That actually brings

92
00:04:14.439 --> 00:04:18.120
<v Speaker 1>us to another major theme in Herman's book, implicit coercion.

93
00:04:18.199 --> 00:04:20.399
<v Speaker 2>Oh yeah, the engine's favorite party trick.

94
00:04:20.680 --> 00:04:24.519
<v Speaker 1>Seriously, the engine is just constantly trying to be forgiving.

95
00:04:24.759 --> 00:04:27.439
<v Speaker 1>For example, the book points out that if you write

96
00:04:27.439 --> 00:04:30.360
<v Speaker 1>the number three plus the boole and true, JavaScript just

97
00:04:30.360 --> 00:04:33.399
<v Speaker 1>decides sure true is basically one, so that equals four.

98
00:04:33.560 --> 00:04:38.040
<v Speaker 1>It just guesses right, or the plus operator being completely overloaded,

99
00:04:38.319 --> 00:04:40.480
<v Speaker 1>like if you add the string two and the number

100
00:04:40.480 --> 00:04:43.000
<v Speaker 1>three breaks the tie and favor strings and just gives

101
00:04:43.040 --> 00:04:44.040
<v Speaker 1>you the string twenty three.

102
00:04:44.199 --> 00:04:48.040
<v Speaker 2>Yeah, it acts like this hyper eager assistant. It sees

103
00:04:48.079 --> 00:04:51.079
<v Speaker 2>a typo or a type mismatch, and instead of just

104
00:04:51.120 --> 00:04:53.680
<v Speaker 2>stopping everything to ask you what you meant, it just

105
00:04:53.759 --> 00:04:57.720
<v Speaker 2>guesses based on this really rigid, hard coded set of rules.

106
00:04:58.399 --> 00:05:00.399
<v Speaker 1>You know, I honestly want to push back on the

107
00:05:00.439 --> 00:05:01.439
<v Speaker 1>author a little bit here.

108
00:05:01.560 --> 00:05:02.240
<v Speaker 2>Okay, go for it.

109
00:05:02.319 --> 00:05:04.680
<v Speaker 1>If the language is genuinely trying to be helpful, why

110
00:05:04.680 --> 00:05:07.600
<v Speaker 1>shouldn't we just let it coerce things? Doesn't it save

111
00:05:07.720 --> 00:05:10.360
<v Speaker 1>us time? I mean, if I tap a string of two,

112
00:05:10.439 --> 00:05:12.839
<v Speaker 1>the computer converting it for me, feels like one less

113
00:05:12.839 --> 00:05:14.639
<v Speaker 1>line of code I have to write I.

114
00:05:14.600 --> 00:05:19.800
<v Speaker 2>Get that, but consider the alternative when that eger assistant

115
00:05:19.839 --> 00:05:23.399
<v Speaker 2>guess is wrong, like semantics usually fail because computers simply

116
00:05:23.399 --> 00:05:26.279
<v Speaker 2>cannot read minds. Fair point. Let's say you have a

117
00:05:26.319 --> 00:05:29.720
<v Speaker 2>variable that's supposed to be a number. Right, You're calculating

118
00:05:29.759 --> 00:05:32.879
<v Speaker 2>a user's cart total on an e commerce site, but

119
00:05:32.959 --> 00:05:36.079
<v Speaker 2>due to some weird bug in an API, it accidentally

120
00:05:36.079 --> 00:05:40.319
<v Speaker 2>becomes null. Okay, not ideal in a stricter language. The

121
00:05:40.480 --> 00:05:42.399
<v Speaker 2>very moment you tried to add a price to null,

122
00:05:42.519 --> 00:05:46.000
<v Speaker 2>the program completely crashes. Y. It stops and tells you

123
00:05:46.040 --> 00:05:49.879
<v Speaker 2>exactly where the error happened. But in JavaScript, JavaScript just

124
00:05:50.160 --> 00:05:54.199
<v Speaker 2>silently coerces null to zero. Oh no, yeah, it just

125
00:05:54.279 --> 00:05:57.560
<v Speaker 2>completes the math. So now your calculation is entirely wrong.

126
00:05:58.000 --> 00:06:00.519
<v Speaker 2>That bad data propagates all the way through your day database,

127
00:06:00.759 --> 00:06:03.160
<v Speaker 2>and your user gets charged the wrong amount. That's horrible,

128
00:06:03.160 --> 00:06:05.120
<v Speaker 2>And the worst part is the error doesn't happen where

129
00:06:05.160 --> 00:06:08.120
<v Speaker 2>the actual mistake was made. It happens like miles down

130
00:06:08.120 --> 00:06:12.040
<v Speaker 2>the road. It makes debugging an absolute nightmare because implicit

131
00:06:12.120 --> 00:06:15.120
<v Speaker 2>coercion hides your type bears instead of catching them.

132
00:06:15.319 --> 00:06:18.319
<v Speaker 1>Okay, yeah, that is a terrifying scenario, which, honestly it

133
00:06:18.399 --> 00:06:20.879
<v Speaker 1>leads us perfectly into Nan not a number. Ugh.

134
00:06:21.319 --> 00:06:25.120
<v Speaker 2>Nan the most ironically named value in the entire language.

135
00:06:24.839 --> 00:06:27.920
<v Speaker 1>Right, considering the type of operator literally classifies Nan as

136
00:06:27.959 --> 00:06:28.480
<v Speaker 1>a number.

137
00:06:28.600 --> 00:06:32.279
<v Speaker 2>It's hilarious. It's a number that means not a number.

138
00:06:32.399 --> 00:06:35.920
<v Speaker 1>And testing for it is notoriously broken. The book mentions

139
00:06:35.920 --> 00:06:39.120
<v Speaker 1>that if you use the strict equality operator nanin equals

140
00:06:39.160 --> 00:06:42.920
<v Speaker 1>so nan actually evaluates to false. Yep, if a value

141
00:06:42.959 --> 00:06:45.920
<v Speaker 1>isn't equal to itself, how do you reliably check for

142
00:06:45.959 --> 00:06:47.480
<v Speaker 1>it without just pulling your hair out?

143
00:06:47.720 --> 00:06:50.639
<v Speaker 2>Well, the author actually provides a brilliant, super reliable trick

144
00:06:50.680 --> 00:06:53.480
<v Speaker 2>for this. You check if a value is unequal to itself.

145
00:06:53.480 --> 00:06:56.120
<v Speaker 2>Wait what Yeah, So if you write x equals x

146
00:06:56.399 --> 00:07:00.199
<v Speaker 2>and that specific statement evaluates to true, then x is

147
00:07:00.199 --> 00:07:03.639
<v Speaker 2>absolutely guaranteed to be nan. Because of that IEE standard

148
00:07:03.720 --> 00:07:06.759
<v Speaker 2>we talked about earlier, Nan is literally the only value

149
00:07:06.759 --> 00:07:09.240
<v Speaker 2>in the entire language where that inequality holds true.

150
00:07:09.319 --> 00:07:12.399
<v Speaker 1>Wow, that is a phenomenal nugget of knowledge, and it

151
00:07:12.399 --> 00:07:14.120
<v Speaker 1>ties right back to why we have to avoid the

152
00:07:14.120 --> 00:07:16.279
<v Speaker 1>double equals operator and just rely on triple equals.

153
00:07:16.360 --> 00:07:17.959
<v Speaker 2>Always use triple equals.

154
00:07:17.639 --> 00:07:21.279
<v Speaker 1>Because double equals triggers that eager assistant to start coercing

155
00:07:21.319 --> 00:07:25.240
<v Speaker 1>types again applying this massive, condoluted table of rules. But

156
00:07:25.319 --> 00:07:30.240
<v Speaker 1>triple equals is strict no coercion, just a direct, honest comparison.

157
00:07:30.480 --> 00:07:34.079
<v Speaker 2>And using strict equality isn't just about avoiding bugs, you know,

158
00:07:34.399 --> 00:07:37.800
<v Speaker 2>It's about communicating your intent to whoever reads your code

159
00:07:37.800 --> 00:07:40.920
<v Speaker 2>six months from now. It basically says, hey, I expect

160
00:07:40.920 --> 00:07:43.759
<v Speaker 2>this exact type and I accept no substitutions.

161
00:07:43.879 --> 00:07:46.519
<v Speaker 1>Absolutely, So the engine is constantly trying to guess our

162
00:07:46.560 --> 00:07:50.600
<v Speaker 1>intent with data types. But this eger assistant behavior. It

163
00:07:50.639 --> 00:07:53.120
<v Speaker 1>doesn't stop at data. No, it actually tries to guess

164
00:07:53.120 --> 00:07:56.079
<v Speaker 1>the structure of your code too. If you forget punctuation,

165
00:07:56.199 --> 00:07:58.480
<v Speaker 1>it will literally rewrite your syntax for you.

166
00:07:58.800 --> 00:08:01.879
<v Speaker 2>Let's talk about automatics Colon insertion or ASI. So.

167
00:08:01.920 --> 00:08:05.000
<v Speaker 1>ASI was originally designed as an error correction mechanism. The

168
00:08:05.079 --> 00:08:08.199
<v Speaker 1>idea was if a developer accidentally leaves off a statement

169
00:08:08.279 --> 00:08:11.800
<v Speaker 1>terminating semicolon, the engine tries to infer where it belongs

170
00:08:11.839 --> 00:08:13.759
<v Speaker 1>and inserts one invisibly.

171
00:08:13.439 --> 00:08:14.720
<v Speaker 2>To keep the script from breaking.

172
00:08:15.040 --> 00:08:17.800
<v Speaker 1>But it gets it wrong. It doesn't actually read your mind.

173
00:08:18.120 --> 00:08:22.879
<v Speaker 1>The book highlights five specific problem characters that completely disable

174
00:08:22.959 --> 00:08:26.639
<v Speaker 1>this insertion, the open parenthesis, the open square bracket, the

175
00:08:26.680 --> 00:08:30.519
<v Speaker 1>plus sign, the minus sign, and the forward slash yeah.

176
00:08:30.560 --> 00:08:34.159
<v Speaker 2>And to visualize this like without looking at a screen,

177
00:08:34.840 --> 00:08:37.799
<v Speaker 2>imagine you write a variable assignment online one, just let

178
00:08:37.840 --> 00:08:40.679
<v Speaker 2>result equals a plus b. Yeah, but you forget the semicolon.

179
00:08:40.879 --> 00:08:41.200
<v Speaker 1>Okay.

180
00:08:41.279 --> 00:08:44.240
<v Speaker 2>Then online two you decide to group some completely separate

181
00:08:44.279 --> 00:08:47.559
<v Speaker 2>map together using an open parenthesis. So line two just

182
00:08:47.600 --> 00:08:49.240
<v Speaker 2>starts with X plus y, right.

183
00:08:49.279 --> 00:08:52.080
<v Speaker 1>And because JavaScript doesn't see a semi coolon online one,

184
00:08:52.279 --> 00:08:54.759
<v Speaker 1>it looks at the open parenthesis online two and assumes

185
00:08:54.759 --> 00:08:57.159
<v Speaker 1>they are connected. It thinks you are trying to call

186
00:08:57.320 --> 00:08:59.799
<v Speaker 1>a plus b as a function and passing x plus

187
00:08:59.840 --> 00:09:00.799
<v Speaker 1>one as the argument.

188
00:09:00.960 --> 00:09:03.200
<v Speaker 2>Exactly. It just jams the two lines together and you

189
00:09:03.200 --> 00:09:06.840
<v Speaker 2>get this completely baffling not a function error. And there's

190
00:09:06.879 --> 00:09:10.080
<v Speaker 2>actually a secondary trap here called restricted productions, where it

191
00:09:10.120 --> 00:09:10.840
<v Speaker 2>does the exact.

192
00:09:10.639 --> 00:09:14.120
<v Speaker 1>Operation where it forcefully inserts a semicolone where you explicitly

193
00:09:14.159 --> 00:09:17.399
<v Speaker 1>did not want one, exactly, a classic return statement bug.

194
00:09:17.679 --> 00:09:21.639
<v Speaker 2>Yes, this gets everyone. Imagine you write the keyword return,

195
00:09:22.200 --> 00:09:24.200
<v Speaker 2>and because you want your code to look really clean

196
00:09:24.200 --> 00:09:27.440
<v Speaker 2>and readable, you hit enter and put the object you're

197
00:09:27.480 --> 00:09:30.600
<v Speaker 2>returning on the next line down makes sense. The JavaScript

198
00:09:30.600 --> 00:09:33.879
<v Speaker 2>engine sees return, hits the new line, and instantly says

199
00:09:34.039 --> 00:09:37.600
<v Speaker 2>oh statement over and just drops an invisible semicolon right

200
00:09:37.639 --> 00:09:38.200
<v Speaker 2>after return.

201
00:09:38.279 --> 00:09:41.960
<v Speaker 1>So your function just silently returns undefined. Yep, and that

202
00:09:42.039 --> 00:09:45.000
<v Speaker 1>beautifully formatted object sitting on the next line is just

203
00:09:45.159 --> 00:09:48.799
<v Speaker 1>dead code. It will never be reached, never invisible bugs.

204
00:09:48.879 --> 00:09:50.200
<v Speaker 1>It's honestly fascinating.

205
00:09:50.320 --> 00:09:52.679
<v Speaker 2>It forces you to realize that white space and new

206
00:09:52.720 --> 00:09:56.559
<v Speaker 2>lines are not just aesthetic in JavaScript like they actively

207
00:09:56.600 --> 00:09:59.799
<v Speaker 2>participate in how the compiler interprets your logic.

208
00:09:59.519 --> 00:10:02.240
<v Speaker 1>Which is a huge mental shift. Yeah, and this invisible

209
00:10:02.240 --> 00:10:05.519
<v Speaker 1>shifting of code brings us to another massive structural quirk

210
00:10:06.279 --> 00:10:07.240
<v Speaker 1>variable hoisting.

211
00:10:07.320 --> 00:10:08.000
<v Speaker 2>Oh hoisting.

212
00:10:08.120 --> 00:10:11.559
<v Speaker 1>JavaScript lacks block scoping, well except for catch blocks. In

213
00:10:11.600 --> 00:10:14.159
<v Speaker 1>a lot of other languages, if you declare a variable

214
00:10:14.159 --> 00:10:16.480
<v Speaker 1>inside an if statement or a for loop, it only

215
00:10:16.519 --> 00:10:19.639
<v Speaker 1>exists within those brackets. It is contained, right But.

216
00:10:19.639 --> 00:10:23.919
<v Speaker 2>In JavaScript using the traditional var keyword, that containment just

217
00:10:24.000 --> 00:10:28.639
<v Speaker 2>doesn't exist. If you declare varx equals five deeply nested

218
00:10:28.679 --> 00:10:32.960
<v Speaker 2>inside a loop, the engine implicitly moves or hoists the

219
00:10:33.039 --> 00:10:36.200
<v Speaker 2>declaration of x to the very top of its enclosing function.

220
00:10:36.960 --> 00:10:40.080
<v Speaker 1>But just the declaration right, not the assignment.

221
00:10:39.919 --> 00:10:42.759
<v Speaker 2>Correct, So the space in memory is created at the top,

222
00:10:43.039 --> 00:10:45.639
<v Speaker 2>but the value of five isn't actually assigned until the

223
00:10:45.679 --> 00:10:48.159
<v Speaker 2>engine runs down to the specific line where you originally

224
00:10:48.159 --> 00:10:48.480
<v Speaker 2>wrote it.

225
00:10:48.519 --> 00:10:51.840
<v Speaker 1>Okay, here's an analogy for hoisting. It's like a stage

226
00:10:51.840 --> 00:10:54.639
<v Speaker 1>director taking all your character introductions and moving them to

227
00:10:54.679 --> 00:10:56.840
<v Speaker 1>the very first scene of the play so the audience

228
00:10:56.879 --> 00:11:00.600
<v Speaker 1>knows they exist. I like this, but the director leaves

229
00:11:00.639 --> 00:11:04.679
<v Speaker 1>their actual costume changes and prop assignments exactly where you

230
00:11:04.720 --> 00:11:05.960
<v Speaker 1>originally wrote them in X two.

231
00:11:06.080 --> 00:11:09.399
<v Speaker 2>Yeah, the director moves the actors but leaves their props behind,

232
00:11:09.600 --> 00:11:12.039
<v Speaker 2>so if they try to use that prop and scene one,

233
00:11:12.200 --> 00:11:14.919
<v Speaker 2>the result is just undefined exactly. And this is why

234
00:11:14.960 --> 00:11:18.279
<v Speaker 2>hoisting causes so many daily bugs. If you don't realize

235
00:11:18.320 --> 00:11:20.519
<v Speaker 2>a loop variable is being hoisted to the top of

236
00:11:20.519 --> 00:11:24.039
<v Speaker 2>your function, you might accidentally overwrite another variable with the

237
00:11:24.080 --> 00:11:25.440
<v Speaker 2>exact same name higher.

238
00:11:25.200 --> 00:11:29.000
<v Speaker 1>Up, which is exactly why the author emphasizes manual hoisting

239
00:11:29.039 --> 00:11:32.639
<v Speaker 1>as a best practice. Just literally write all your VAW

240
00:11:32.679 --> 00:11:35.360
<v Speaker 1>declarations at the very top of your function manually.

241
00:11:35.480 --> 00:11:37.360
<v Speaker 2>Yeah, be your own stage director.

242
00:11:37.120 --> 00:11:40.759
<v Speaker 1>Right, because it visually matches how the engine actually interprets

243
00:11:40.759 --> 00:11:43.919
<v Speaker 1>the code, which saves you from those crazy loop variable

244
00:11:44.120 --> 00:11:48.559
<v Speaker 1>overwrite bugs. You are basically organizing the actors before the

245
00:11:48.600 --> 00:11:49.559
<v Speaker 1>play begins.

246
00:11:49.799 --> 00:11:52.000
<v Speaker 2>It really is about writing code the way the compiler

247
00:11:52.039 --> 00:11:55.679
<v Speaker 2>reads it. When your mental model matches the engine's mechanical model,

248
00:11:56.000 --> 00:11:57.159
<v Speaker 2>the bugs just disappear.

249
00:11:57.600 --> 00:12:00.799
<v Speaker 1>So true. Okay, so hoisting shows us how jobscript moves

250
00:12:00.919 --> 00:12:05.000
<v Speaker 1>variable declarations around in a function's scope. But what happens

251
00:12:05.039 --> 00:12:07.399
<v Speaker 1>when functions hold onto those variables across time?

252
00:12:07.759 --> 00:12:08.919
<v Speaker 2>Now we're getting to the good stuff.

253
00:12:09.000 --> 00:12:11.080
<v Speaker 1>Yeah, this brings us to what might be the language's

254
00:12:11.120 --> 00:12:14.720
<v Speaker 1>most powerful expressive feature closures.

255
00:12:14.879 --> 00:12:17.919
<v Speaker 2>Closures are incredibly elegant once you strip away all the

256
00:12:17.919 --> 00:12:22.200
<v Speaker 2>computer science jargon. In really simple terms, a closure allows

257
00:12:22.200 --> 00:12:25.919
<v Speaker 2>a function to remember variables from its outer scope even

258
00:12:25.960 --> 00:12:29.039
<v Speaker 2>after that outer function has completely finished executing. In return,

259
00:12:29.320 --> 00:12:29.600
<v Speaker 2>it's like.

260
00:12:29.600 --> 00:12:32.000
<v Speaker 1>A memory that outlives the event itself.

261
00:12:32.360 --> 00:12:33.399
<v Speaker 2>That's a great way to put it.

262
00:12:33.480 --> 00:12:38.039
<v Speaker 1>But here is the crucial, often misunderstood detail from Herman's book.

263
00:12:38.919 --> 00:12:43.159
<v Speaker 1>Closures store references to their outer variables. They do not

264
00:12:43.320 --> 00:12:46.320
<v Speaker 1>store copies of their values at that frozen moment in time.

265
00:12:46.480 --> 00:12:50.879
<v Speaker 2>Yes, and this specific detail trips up seasoned developers constantly

266
00:12:51.559 --> 00:12:54.600
<v Speaker 2>because it's a reference. It means the closure is looking

267
00:12:54.679 --> 00:12:55.799
<v Speaker 2>at a live variable.

268
00:12:55.879 --> 00:12:56.879
<v Speaker 1>Okay, give me an example.

269
00:12:57.360 --> 00:13:00.440
<v Speaker 2>Think about a for loop that runs three times from

270
00:13:00.519 --> 00:13:04.279
<v Speaker 2>zero to two. Inside that loop, you create three different

271
00:13:04.320 --> 00:13:07.279
<v Speaker 2>button click functions, and each one is supposed to print

272
00:13:07.360 --> 00:13:08.360
<v Speaker 2>the current loop number.

273
00:13:08.440 --> 00:13:10.840
<v Speaker 1>Okay, so you would logically expect the first button to

274
00:13:10.840 --> 00:13:13.000
<v Speaker 1>print zero, the second to print one, and the third

275
00:13:13.039 --> 00:13:14.919
<v Speaker 1>to print two naturally, but.

276
00:13:15.200 --> 00:13:17.320
<v Speaker 2>They don't capture a frozen copy of the number. They

277
00:13:17.360 --> 00:13:19.759
<v Speaker 2>capture a live reference to the single variable eye.

278
00:13:19.840 --> 00:13:20.039
<v Speaker 1>Oh.

279
00:13:20.480 --> 00:13:22.320
<v Speaker 2>So, by the time the loop is finished running, I

280
00:13:22.519 --> 00:13:26.360
<v Speaker 2>is incremented to its maximum value, which is three. Later,

281
00:13:26.639 --> 00:13:29.279
<v Speaker 2>when a user finally clicks one of those buttons, the

282
00:13:29.360 --> 00:13:31.799
<v Speaker 2>closure looks up the current value of IE, and every

283
00:13:31.799 --> 00:13:33.200
<v Speaker 2>single button just prints three.

284
00:13:33.320 --> 00:13:36.279
<v Speaker 1>That is so frustrating. So to fix it, you basically

285
00:13:36.320 --> 00:13:39.240
<v Speaker 1>have to freeze time for each iteration. You can't just

286
00:13:39.320 --> 00:13:42.879
<v Speaker 1>let the closure point to the main loop variable, right, You.

287
00:13:42.799 --> 00:13:46.519
<v Speaker 2>Need to force a brand new, completely isolated local scope

288
00:13:46.799 --> 00:13:50.440
<v Speaker 2>for every single iteration. And the classic JavaScript workaround for

289
00:13:50.480 --> 00:13:55.159
<v Speaker 2>this is using an IIE an immediately invoked function expression.

290
00:13:55.200 --> 00:13:57.639
<v Speaker 1>Okay, let's slow that down for the listener. How exactly

291
00:13:57.679 --> 00:13:59.399
<v Speaker 1>does an IE freeze time?

292
00:13:59.519 --> 00:14:01.840
<v Speaker 2>Okay, so instead of just creating the closure directly in

293
00:14:01.879 --> 00:14:06.039
<v Speaker 2>the loop, you wrap it inside a completely separate temporary function.

294
00:14:06.399 --> 00:14:08.799
<v Speaker 2>You pass the current loop number into that temporary function

295
00:14:08.840 --> 00:14:11.120
<v Speaker 2>as an argument, and you command the engine to run

296
00:14:11.159 --> 00:14:12.360
<v Speaker 2>it right then and there.

297
00:14:12.440 --> 00:14:15.440
<v Speaker 1>Ah immediately invoked exactly.

298
00:14:15.360 --> 00:14:18.000
<v Speaker 2>That temporary function locks the value in place for that

299
00:14:18.039 --> 00:14:21.919
<v Speaker 2>specific iteration, and then returns your closure safely sealed inside

300
00:14:21.960 --> 00:14:22.960
<v Speaker 2>that frozen environment.

301
00:14:23.279 --> 00:14:25.080
<v Speaker 1>Okay, Wait, I have an insight here. I want to

302
00:14:25.120 --> 00:14:28.519
<v Speaker 1>test with you. Sure, if closures store live references rather

303
00:14:28.519 --> 00:14:32.399
<v Speaker 1>than static values, doesn't that mean multiple closures can actually

304
00:14:32.399 --> 00:14:36.320
<v Speaker 1>communicate by modifying the exact same outer variable.

305
00:14:36.679 --> 00:14:39.360
<v Speaker 2>Yes, you just hit on one of the most powerful

306
00:14:39.480 --> 00:14:42.360
<v Speaker 2>architectural patterns in the language. Really, yeah, it's not a

307
00:14:42.399 --> 00:14:45.559
<v Speaker 2>bug at all, it's a massive superpower. This is the

308
00:14:45.600 --> 00:14:50.000
<v Speaker 2>foundation of the box pattern. Imagine a function that defines

309
00:14:50.039 --> 00:14:54.559
<v Speaker 2>a single private variable, say a bank account balance. Okay,

310
00:14:55.240 --> 00:14:59.399
<v Speaker 2>then that function returns an object containing two closures, a

311
00:14:59.440 --> 00:15:01.840
<v Speaker 2>deposit function and a withdraw function.

312
00:15:01.960 --> 00:15:04.720
<v Speaker 1>And because they were both created in the same outer scope,

313
00:15:04.759 --> 00:15:08.080
<v Speaker 1>they share the exact same live reference to that one

314
00:15:08.159 --> 00:15:09.039
<v Speaker 1>balance variable.

315
00:15:09.120 --> 00:15:13.000
<v Speaker 2>Precisely, so, if the deposit closure adds money, the withdraw

316
00:15:13.039 --> 00:15:15.480
<v Speaker 2>closure will instantly see the new balance because they are

317
00:15:15.480 --> 00:15:17.639
<v Speaker 2>looking at the exact same space in memory.

318
00:15:17.799 --> 00:15:21.320
<v Speaker 1>Wow. And because that balance variable was declared inside a

319
00:15:21.360 --> 00:15:25.000
<v Speaker 1>function that has already returned, it is completely invisible to

320
00:15:25.039 --> 00:15:25.879
<v Speaker 1>the rest of the program.

321
00:15:25.960 --> 00:15:26.840
<v Speaker 2>Yep, untouchable.

322
00:15:26.879 --> 00:15:30.879
<v Speaker 1>You get true encapsulation, true private state without needing traditional

323
00:15:30.879 --> 00:15:34.080
<v Speaker 1>classes or complex architecture. The outside world can only touch

324
00:15:34.120 --> 00:15:37.200
<v Speaker 1>the balance using the specific closures you explicitly handed back.

325
00:15:37.399 --> 00:15:41.480
<v Speaker 2>It's brilliant, lightweight encapsulation. It's what makes JavaScript so unique.

326
00:15:41.639 --> 00:15:45.879
<v Speaker 1>I love that. So closures are all about how functions

327
00:15:46.080 --> 00:15:50.879
<v Speaker 1>capture their surrounding environment. But a function's identity itself changes

328
00:15:51.000 --> 00:15:53.120
<v Speaker 1>entirely depending on exactly how you invoke it.

329
00:15:53.360 --> 00:15:54.720
<v Speaker 2>Oh boy, Yeah, I'm talking.

330
00:15:54.559 --> 00:15:58.600
<v Speaker 1>About the chameleon nature of functions and the dreaded this keyword.

331
00:15:58.480 --> 00:16:01.240
<v Speaker 2>The binding of this is arguable the single biggest source

332
00:16:01.240 --> 00:16:03.000
<v Speaker 2>of hair pulling in JavaScript history.

333
00:16:03.039 --> 00:16:04.639
<v Speaker 1>I've lost a few hairs to it myself.

334
00:16:04.840 --> 00:16:08.720
<v Speaker 2>We all have. And the confusion stems from treating JavaScript

335
00:16:08.720 --> 00:16:11.879
<v Speaker 2>functions like they are static. They aren't. You have to

336
00:16:11.960 --> 00:16:15.120
<v Speaker 2>understand the difference between calling a function, calling a method,

337
00:16:15.320 --> 00:16:16.559
<v Speaker 2>and calling a constructor.

338
00:16:16.879 --> 00:16:19.159
<v Speaker 1>But it can be the exact same block of code,

339
00:16:19.159 --> 00:16:21.200
<v Speaker 1>literally the exact same text on the screen.

340
00:16:21.320 --> 00:16:23.879
<v Speaker 2>I know, but the text doesn't matter. The syntax of

341
00:16:23.919 --> 00:16:27.279
<v Speaker 2>the invocation changes everything. When you invoke code, the engine

342
00:16:27.320 --> 00:16:29.279
<v Speaker 2>assigns a receiver to the keyword this.

343
00:16:29.600 --> 00:16:29.879
<v Speaker 1>Okay.

344
00:16:30.080 --> 00:16:32.759
<v Speaker 2>If you call it purely as a standard function like

345
00:16:32.919 --> 00:16:38.399
<v Speaker 2>just hello, this binding defaults to pointing at the global object,

346
00:16:39.279 --> 00:16:42.240
<v Speaker 2>or it becomes undefined. If you're operating in strict mode.

347
00:16:42.360 --> 00:16:46.200
<v Speaker 1>That feels incredibly dangerous. If you accidentally use this thinking

348
00:16:46.240 --> 00:16:50.159
<v Speaker 1>you are modifying a local property, you could be accidentally

349
00:16:50.159 --> 00:16:51.759
<v Speaker 1>overwriting global variables.

350
00:16:51.879 --> 00:16:54.720
<v Speaker 2>You absolutely could, and people do. Now. If you call

351
00:16:54.759 --> 00:16:57.320
<v Speaker 2>it as a method, meaning it is attached to an

352
00:16:57.320 --> 00:17:01.840
<v Speaker 2>object like user dot hello, then this is securely bound

353
00:17:01.879 --> 00:17:05.000
<v Speaker 2>to the user object. The object itself becomes the receiver.

354
00:17:05.200 --> 00:17:06.839
<v Speaker 1>Okay, that makes sense. And what if you call it

355
00:17:06.839 --> 00:17:09.480
<v Speaker 1>with the new keyword like new hello.

356
00:17:09.599 --> 00:17:13.319
<v Speaker 2>Then the function completely transforms into a constructor. The engine

357
00:17:13.359 --> 00:17:16.559
<v Speaker 2>creates a brand new empty object on the fly and

358
00:17:16.680 --> 00:17:19.119
<v Speaker 2>binds this to that new object for the duration of

359
00:17:19.119 --> 00:17:19.519
<v Speaker 2>the function.

360
00:17:19.680 --> 00:17:22.440
<v Speaker 1>Okay, here's my analogy for this chameleon behavior. Tell me

361
00:17:22.480 --> 00:17:23.000
<v Speaker 1>if this works.

362
00:17:23.079 --> 00:17:23.519
<v Speaker 2>Let's here it.

363
00:17:23.839 --> 00:17:27.200
<v Speaker 1>A JavaScript function is like a highly versatile actor. If

364
00:17:27.200 --> 00:17:29.480
<v Speaker 1>you call it normally, the actor is performing out on

365
00:17:29.519 --> 00:17:33.960
<v Speaker 1>the street that's the global object. Anything goes usually chaos. Sure,

366
00:17:34.359 --> 00:17:36.240
<v Speaker 1>if you call it as a method, they are performing

367
00:17:36.279 --> 00:17:38.839
<v Speaker 1>on a specific set, like a living room. And if

368
00:17:38.880 --> 00:17:41.200
<v Speaker 1>you use new the engine builds them a brand new

369
00:17:41.200 --> 00:17:42.839
<v Speaker 1>stage right in front of your eyes.

370
00:17:42.960 --> 00:17:44.720
<v Speaker 2>I think that's a perfect way to visualize it.

371
00:17:45.000 --> 00:17:47.559
<v Speaker 1>But what if I want to guarantee where they perform?

372
00:17:48.000 --> 00:17:50.920
<v Speaker 1>What if I extract a method and pass it around.

373
00:17:51.160 --> 00:17:55.440
<v Speaker 2>Ah, that is where the danger peaks. Think about passing

374
00:17:55.440 --> 00:17:58.720
<v Speaker 2>a method as a callback. You have user dot log in,

375
00:17:59.359 --> 00:18:01.839
<v Speaker 2>and you pass that to a higher order function like

376
00:18:01.880 --> 00:18:03.039
<v Speaker 2>an arraise dot for each.

377
00:18:03.160 --> 00:18:04.759
<v Speaker 1>Happens all the time, right, But.

378
00:18:04.759 --> 00:18:07.599
<v Speaker 2>When you hand user dot log in too for each,

379
00:18:08.200 --> 00:18:10.720
<v Speaker 2>you aren't handing it the user object. You are just

380
00:18:10.839 --> 00:18:12.920
<v Speaker 2>handing it the raw unattached function.

381
00:18:13.119 --> 00:18:15.559
<v Speaker 1>Oh you strip away the receiver exactly.

382
00:18:15.759 --> 00:18:18.480
<v Speaker 2>When four each eventually calls your callback, it calls it

383
00:18:18.519 --> 00:18:21.759
<v Speaker 2>as a plane unattached function. The actor is back on

384
00:18:21.799 --> 00:18:22.200
<v Speaker 2>the street.

385
00:18:22.319 --> 00:18:22.839
<v Speaker 1>Oh wow.

386
00:18:22.960 --> 00:18:25.480
<v Speaker 2>Yeah, So this suddenly points to the global object and

387
00:18:25.559 --> 00:18:29.480
<v Speaker 2>your program crashes because the login properties it expects simply

388
00:18:29.480 --> 00:18:29.960
<v Speaker 2>aren't there.

389
00:18:30.200 --> 00:18:32.720
<v Speaker 1>So, if you, the listener, have ever passed a callback

390
00:18:32.759 --> 00:18:35.880
<v Speaker 1>to a higher order function and watched your application basically

391
00:18:35.920 --> 00:18:38.400
<v Speaker 1>catch fire, because this suddenly pointed to the wrong place.

392
00:18:38.839 --> 00:18:40.640
<v Speaker 1>This is why you lost your receiver.

393
00:18:40.839 --> 00:18:41.039
<v Speaker 2>Yep.

394
00:18:41.480 --> 00:18:43.559
<v Speaker 1>So how do we fix the actor's contract? How do

395
00:18:43.640 --> 00:18:45.319
<v Speaker 1>we stop them from going back to the street.

396
00:18:45.640 --> 00:18:48.759
<v Speaker 2>You use the dot bind method. Calling dot bind on

397
00:18:48.839 --> 00:18:51.960
<v Speaker 2>a function creates a new wrapper function that permanently locks

398
00:18:52.000 --> 00:18:52.599
<v Speaker 2>down the receiver.

399
00:18:52.839 --> 00:18:55.480
<v Speaker 1>So it gives the actor an ironclad contract to only

400
00:18:55.519 --> 00:18:58.680
<v Speaker 1>perform in one specific theater, no matter who hires them

401
00:18:58.839 --> 00:19:01.359
<v Speaker 1>or when they get called later. You safely lock this

402
00:19:01.440 --> 00:19:01.880
<v Speaker 1>in place.

403
00:19:02.000 --> 00:19:04.839
<v Speaker 2>Yes, is the ultimate safeguard for callbacks.

404
00:19:05.119 --> 00:19:09.480
<v Speaker 1>That's incredibly useful. Now, understanding functions as constructors. Using that

405
00:19:09.599 --> 00:19:13.279
<v Speaker 1>new keyword naturally leads us to our final destination today.

406
00:19:14.039 --> 00:19:18.039
<v Speaker 1>How JavaScript actually builds objects and shares behavior.

407
00:19:17.680 --> 00:19:18.759
<v Speaker 2>The prototype system.

408
00:19:18.880 --> 00:19:22.680
<v Speaker 1>Yes, we are ditching traditional blueprints for something far more dynamic.

409
00:19:22.880 --> 00:19:24.119
<v Speaker 1>Let's talk about prototypes.

410
00:19:24.319 --> 00:19:28.039
<v Speaker 2>This requires a major mental shift. JavaScript does not have

411
00:19:28.079 --> 00:19:31.440
<v Speaker 2>built in classes in the traditional object oriented sense like

412
00:19:31.559 --> 00:19:33.480
<v Speaker 2>Java or C plus plus man.

413
00:19:33.440 --> 00:19:34.720
<v Speaker 1>Which shocks a lot of people.

414
00:19:34.880 --> 00:19:38.160
<v Speaker 2>It really does. It relies entirely on prototypes, which is

415
00:19:38.160 --> 00:19:41.720
<v Speaker 2>a system of implementation inheritance through dynamic delegation.

416
00:19:42.160 --> 00:19:46.960
<v Speaker 1>Okay, before we explain delegation, let's untangle a massive naming

417
00:19:47.119 --> 00:19:48.839
<v Speaker 1>overlap that the book brings up because I know it

418
00:19:48.880 --> 00:19:54.000
<v Speaker 1>confuses everyone the difference between the propertyconstructor dot prototype and

419
00:19:54.039 --> 00:19:56.119
<v Speaker 1>the function object dot get.

420
00:19:56.039 --> 00:19:59.559
<v Speaker 2>Prototypeo Oh, it's a naming disaster, honestly, it really is.

421
00:19:59.759 --> 00:20:02.680
<v Speaker 2>So when you see a property called dot prototype on

422
00:20:02.720 --> 00:20:06.599
<v Speaker 2>a constructor function dash like user about prototype, that is

423
00:20:06.680 --> 00:20:09.000
<v Speaker 2>not the prototype of the user function itself.

424
00:20:09.079 --> 00:20:09.319
<v Speaker 1>Wait?

425
00:20:09.440 --> 00:20:13.000
<v Speaker 2>Really no, that is the object that will be assigned

426
00:20:13.079 --> 00:20:15.880
<v Speaker 2>as the prototype for all future objects created when you

427
00:20:15.920 --> 00:20:17.400
<v Speaker 2>eventually call new user.

428
00:20:17.599 --> 00:20:20.559
<v Speaker 1>Ah. Okay, so it's the template for the future generation.

429
00:20:20.799 --> 00:20:23.200
<v Speaker 2>Yes, but if you want to find the prototype of

430
00:20:23.200 --> 00:20:26.279
<v Speaker 2>an existing, already created object, you don't look for a

431
00:20:26.279 --> 00:20:28.759
<v Speaker 2>dot prototype property. You have to use the standard built

432
00:20:28.759 --> 00:20:31.359
<v Speaker 2>in function object dot get prototype of and pass your

433
00:20:31.400 --> 00:20:33.160
<v Speaker 2>existing object right into it. Got it?

434
00:20:33.519 --> 00:20:36.720
<v Speaker 1>Okay, So template for the future versus checking the current reality.

435
00:20:36.839 --> 00:20:37.000
<v Speaker 2>Now.

436
00:20:37.079 --> 00:20:40.359
<v Speaker 1>The book heavily emphasizes why we must store our methods

437
00:20:40.400 --> 00:20:42.759
<v Speaker 1>on these prototypes rather than just putting them inside the

438
00:20:42.799 --> 00:20:45.119
<v Speaker 1>constructor function itself. Why is that so important?

439
00:20:45.319 --> 00:20:48.960
<v Speaker 2>It all comes down to sheer memory efficiency. Imagine you

440
00:20:49.000 --> 00:20:52.160
<v Speaker 2>are building a game, right and you put a method

441
00:20:52.160 --> 00:20:55.440
<v Speaker 2>inside the constructor just not attack function and so on.

442
00:20:55.519 --> 00:20:58.880
<v Speaker 2>Pretty standard, but every single time you create a new

443
00:20:59.079 --> 00:21:04.279
<v Speaker 2>enemy instance, the JavaScript engine allocates fresh memory for a

444
00:21:04.319 --> 00:21:08.400
<v Speaker 2>brand new function object. Yeah, if you spawn ten thousand enemies,

445
00:21:08.599 --> 00:21:12.319
<v Speaker 2>you have ten thousand identical function objects just clogging up

446
00:21:12.319 --> 00:21:13.240
<v Speaker 2>your computer's memory.

447
00:21:13.279 --> 00:21:16.240
<v Speaker 1>Oh that's incredibly wasteful. But if you put the attack

448
00:21:16.319 --> 00:21:17.839
<v Speaker 1>method on the prototype, you.

449
00:21:17.799 --> 00:21:20.880
<v Speaker 2>Stored in memory exactly once, just once, just once. All

450
00:21:20.960 --> 00:21:24.720
<v Speaker 2>ten thousand enemy objects are completely empty of methods, but

451
00:21:24.799 --> 00:21:27.920
<v Speaker 2>they all have a hidden link to that single prototype object.

452
00:21:28.200 --> 00:21:30.640
<v Speaker 2>So when you call enemy dot attack, the object says,

453
00:21:31.000 --> 00:21:33.599
<v Speaker 2>I don't have that method here. Let me dynamically delegate

454
00:21:33.599 --> 00:21:35.279
<v Speaker 2>this request up to my prototype, and.

455
00:21:35.240 --> 00:21:36.920
<v Speaker 1>It finds the shared method exactly.

456
00:21:36.960 --> 00:21:38.880
<v Speaker 2>It finds a single shared method and runs it. It's

457
00:21:38.880 --> 00:21:39.640
<v Speaker 2>incredibly lean.

458
00:21:39.839 --> 00:21:43.359
<v Speaker 1>That delegation is beautiful. But I have a fundamental question here.

459
00:21:43.640 --> 00:21:46.759
<v Speaker 1>If prototypes are so radically different from classes, and they're

460
00:21:46.799 --> 00:21:50.759
<v Speaker 1>so incredibly memory efficient, why do programmers constantly try to

461
00:21:50.839 --> 00:21:55.640
<v Speaker 1>force class like syntax and strict hierarchies onto JavaScript. Isn't

462
00:21:55.720 --> 00:21:59.359
<v Speaker 1>dynamic delegation actually simpler once you just stop fighting it.

463
00:21:59.359 --> 00:22:02.079
<v Speaker 2>It's just human nature, you know. We gravitate toward what

464
00:22:02.079 --> 00:22:05.279
<v Speaker 2>we know. The vast majority of developers cut their teeth

465
00:22:05.359 --> 00:22:09.079
<v Speaker 2>on Java C sharp or C plus plus A, where

466
00:22:09.200 --> 00:22:12.559
<v Speaker 2>static rigid classes are literally the only way to model

467
00:22:12.599 --> 00:22:16.960
<v Speaker 2>the world, it feels safe. Shifting to JavaScript requires unlearning

468
00:22:17.000 --> 00:22:18.519
<v Speaker 2>some deeply ingrained habits.

469
00:22:18.519 --> 00:22:20.119
<v Speaker 1>You really have to let go of the bluepress.

470
00:22:20.160 --> 00:22:23.720
<v Speaker 2>You do, But once you actually embrace prototypal delegation, you

471
00:22:23.799 --> 00:22:27.119
<v Speaker 2>realize it's this deeply flexible system. It allows you to

472
00:22:27.160 --> 00:22:29.759
<v Speaker 2>easily clone objects, swap out behaviors on the fly, and

473
00:22:29.839 --> 00:22:33.000
<v Speaker 2>just mix and match properties without the rigid bureaucracy of

474
00:22:33.160 --> 00:22:34.440
<v Speaker 2>massive class taxonomies.

475
00:22:34.519 --> 00:22:36.119
<v Speaker 1>That sounds so freeing it is.

476
00:22:36.160 --> 00:22:39.960
<v Speaker 2>You aren't building inescapable rigid family trees. You're just dynamically

477
00:22:40.000 --> 00:22:41.839
<v Speaker 2>linking objects to other objects.

478
00:22:42.000 --> 00:22:44.039
<v Speaker 1>So what does this all mean for you, the listener?

479
00:22:44.599 --> 00:22:47.880
<v Speaker 1>Let's recap this journey. We have systematically stripped away the

480
00:22:47.920 --> 00:22:49.400
<v Speaker 1>illusions of JavaScript today.

481
00:22:49.559 --> 00:22:52.079
<v Speaker 2>We covered a lot of ground we really did.

482
00:22:52.279 --> 00:22:55.720
<v Speaker 1>From those pseudo integers causing binary math failures to the

483
00:22:55.920 --> 00:23:00.599
<v Speaker 1>sneaky invisible semicolons rewriting your syntax behind your back. We

484
00:23:00.799 --> 00:23:04.960
<v Speaker 1>uncovered how variable horsting moves your actors around, how closures

485
00:23:05.039 --> 00:23:09.359
<v Speaker 1>capture live references to create private state, The chameleon nature

486
00:23:09.400 --> 00:23:13.000
<v Speaker 1>of this keyword and finally, the memory saving power of

487
00:23:13.160 --> 00:23:14.440
<v Speaker 1>classless prototypes.

488
00:23:14.519 --> 00:23:16.960
<v Speaker 2>Yeah, we now see the language for what it truly

489
00:23:17.079 --> 00:23:18.880
<v Speaker 2>is beneath the surface exactly.

490
00:23:19.039 --> 00:23:22.400
<v Speaker 1>It's a language that demands respect for its internal mechanics.

491
00:23:22.559 --> 00:23:25.640
<v Speaker 1>You simply cannot just skim the surface and expect your

492
00:23:25.680 --> 00:23:27.160
<v Speaker 1>code to scale predictably.

493
00:23:27.240 --> 00:23:29.119
<v Speaker 2>You really can't. It'll catch up with you.

494
00:23:29.319 --> 00:23:31.279
<v Speaker 1>It demands that respect. And I want to leave you

495
00:23:31.319 --> 00:23:34.480
<v Speaker 1>with one final provocative thought to explore on your own.

496
00:23:35.079 --> 00:23:38.119
<v Speaker 1>We just talked about checking and setting prototypes safely using

497
00:23:38.160 --> 00:23:42.039
<v Speaker 1>standard methods, But lurking in the shadows of JavaScript is

498
00:23:42.079 --> 00:23:45.759
<v Speaker 1>a dark, non standard property called proto that is proto

499
00:23:45.880 --> 00:23:47.920
<v Speaker 1>spelled with two underscores on each side.

500
00:23:47.960 --> 00:23:51.039
<v Speaker 2>Oh wow, a truly terrifying amount of power.

501
00:23:50.920 --> 00:23:54.279
<v Speaker 1>It really is. Modifying an object's proto dynamically is quite

502
00:23:54.359 --> 00:23:57.519
<v Speaker 1>literally like giving the object a brain transplant at runtime.

503
00:23:57.599 --> 00:23:58.359
<v Speaker 2>Yeah, don't do it.

504
00:23:58.359 --> 00:24:02.759
<v Speaker 1>It completely invalidates the job. Abscript engines internal performance optimizations,

505
00:24:02.799 --> 00:24:06.640
<v Speaker 1>and it swaps the objects entire inheritance hierarchy on the fly.

506
00:24:07.240 --> 00:24:09.480
<v Speaker 1>The author of our source text warns that you should

507
00:24:09.519 --> 00:24:11.400
<v Speaker 1>never modify it in production CAD.

508
00:24:11.640 --> 00:24:15.160
<v Speaker 2>It is the ultimate dynamic temptation, best left entirely alone.

509
00:24:15.519 --> 00:24:19.720
<v Speaker 1>Let the shadow remain a shadow, just something fascinating to ponder.

510
00:24:19.759 --> 00:24:23.039
<v Speaker 1>The next time you think you are in complete safe control.

511
00:24:22.680 --> 00:24:24.440
<v Speaker 2>Of your objects, good luck out there.

512
00:24:24.599 --> 00:24:27.319
<v Speaker 1>So the next time you are debugging and things get murky,

513
00:24:27.400 --> 00:24:30.640
<v Speaker 1>remember the diagnostic X ray machine might be broken, but

514
00:24:30.680 --> 00:24:33.240
<v Speaker 1>now you understand the physics of the machine itself. Thanks

515
00:24:33.240 --> 00:24:34.720
<v Speaker 1>for taking the deep dive with us.
