WEBVTT

1
00:00:01.200 --> 00:00:04.159
Look at this function makeCounter.

2
00:00:04.462 --> 00:00:09.569
It creates a local variable, count, which is set to zero.

3
00:00:09.966 --> 00:00:18.218
Then it creates a second function inside itself, and returns that function without running it.

4
00:00:18.418 --> 00:00:24.407
You already know what happens to a local variable when its function returns.

5
00:00:24.490 --> 00:00:25.545
It's gone.

6
00:00:25.756 --> 00:00:30.038
So look at what that inner function is about to do.

7
00:00:30.249 --> 00:00:33.230
It adds one to count, but how?

8
00:00:33.441 --> 00:00:36.179
Hasn't count already gone away?

9
00:00:36.880 --> 00:00:43.461
The truth is that the local variable actually doesn't go away because of something called a closure.

10
00:00:43.602 --> 00:00:51.495
In JavaScript, a closure is an inner function that retains variables from the place it was created.

11
00:00:51.891 --> 00:00:55.152
Name the returned function tally.

12
00:00:55.352 --> 00:01:00.609
In many languages, a local variable lives and dies with the call.

13
00:01:00.913 --> 00:01:09.352
In JavaScript, the variable lives for as long as something can still reach it, and the function tally can reach it.

14
00:01:09.552 --> 00:01:10.839
Call tally.

15
00:01:10.980 --> 00:01:11.872
One.

16
00:01:12.083 --> 00:01:13.672
Call it again.

17
00:01:13.883 --> 00:01:15.750
Now it is two.

18
00:01:16.054 --> 00:01:16.957
Again.

19
00:01:17.168 --> 00:01:18.049
Three.

20
00:01:18.352 --> 00:01:25.827
makeCounter finished long ago, and yet count is still there, keeping its value between calls.

21
00:01:26.527 --> 00:01:32.051
Call makeCounter a second time and you get a new box, with its own count.

22
00:01:32.262 --> 00:01:36.858
Each one counts separately, because they don't share anything.

23
00:01:37.058 --> 00:01:42.861
The function holds the variable itself, not a snapshot of its value.

24
00:01:43.165 --> 00:01:48.132
That's why each call sees what the last call left.

25
00:01:48.332 --> 00:01:50.257
And no one else can get in.

26
00:01:50.468 --> 00:01:54.495
Ask tally for a count property, and you get undefined.

27
00:01:54.799 --> 00:02:01.960
The only way to that variable is through the function, so no other code can touch it.

28
00:02:02.660 --> 00:02:11.052
You use these every time you hand a function to the browser, to run on a click, a timer, or a response from the network.

29
00:02:11.193 --> 00:02:15.882
By the time it runs, the code that created it has finished.

30
00:02:15.965 --> 00:02:19.295
It reaches those variables through its closure.

31
00:02:19.506 --> 00:02:29.709
That's why closures were fundamental to JavaScript-powered HTTP communications, often dubbed Ajax, and they still are.

32
00:02:30.410 --> 00:02:33.938
Now the bug that caught JavaScript programmers for years.

33
00:02:34.241 --> 00:02:43.086
This loop sets three timers, and each should print its own pass through the loop: zero, one, two.

34
00:02:43.378 --> 00:02:47.010
It prints three, three, three.

35
00:02:47.210 --> 00:02:48.694
You now know why.

36
00:02:49.137 --> 00:02:57.566
The var statement has function scope, so there's one variable named i, and all three functions hold that same variable.

37
00:02:57.566 --> 00:03:03.602
The timers run after the loop ends, and by that point the value of i is three.

38
00:03:03.848 --> 00:03:09.569
Each function is reading the variable as it is now, and not as it was.

39
00:03:10.269 --> 00:03:13.007
Change the declaration from var to let.

40
00:03:13.288 --> 00:03:22.516
The let at the head of a for loop gives each pass a new variable, so there are three boxes now, and each function holds its own.

41
00:03:22.808 --> 00:03:25.407
Zero, one, two.

42
00:03:25.687 --> 00:03:27.624
The functions didn't change.

43
00:03:27.638 --> 00:03:31.699
What changed is how many variables they had to hold.

44
00:03:32.399 --> 00:03:36.031
There's a cost, and it follows from the same rule.

45
00:03:36.335 --> 00:03:42.637
What a closure can reach can't be collected while the closure itself can be reached.

46
00:03:42.848 --> 00:03:56.151
A handler you never remove can hold on to its variables for the life of the page, which can lead to a memory leak, so make sure you understand closures and clean up after yourself.

47
00:03:56.352 --> 00:04:05.708
So when you look over closures, ask the question, "Which variable does this function hold on to, and who else is holding it?"

48
00:04:06.104 --> 00:04:13.835
Try the playgrounds in the Functions and Closures article, and explore this powerful idea yourself.
