Check out a free preview of the full JavaScript: The Hard Parts course:
The "Power of Closure" Lesson is part of the full, JavaScript: The Hard Parts course featured in this preview video. Here's what you'd learn in this lesson:

After reviewing the lessons so far in the course, Will illustrates that closure can be used to store data and used to implement module patterns in JavaScript.

Get Unlimited Access Now

Transcript from the "Power of Closure" Lesson

[00:00:00]
>> Speaker 1: We have achieved something really remarkable here. We have given our function definitions. It ain't just function definitions anymore. They're function definitions plus live data stores attached to the back of them. They're all mini caches, a persistent state, little state stores that were created. my keyword salad, were created by the fact that these functions were themselves defined inside another function being called.

[00:00:28] And they therefore, got this little bond to their surrounding live memory. And that bond didn't go way when that inner function returned out and stored in its new label, very profound. So what's this else do? Well, if you go back at the very beginning we said, what does it say?

[00:00:46] We said, what if our functions could hold on to live data/state between their executions? Well, what do you know? They can, this will let our function definitions have an associated persistent memory. This would let us do things like, well, create these highly professional functions like once, memoize, basically any function that needs the memory of the past timers run.

[00:01:14] So one of them would be called once. So the onceified version of multiply by 2 would say, first time you run me, I'm gonna multiply by 2 functions that's got a memory of the last time I run. First time you run me, with input of 3 multiplied by 2 return 6.

[00:01:31] Okay, fine good. But, don't just return, 6, also have a little counter in my backpack, write the function in such a way that when you run me, also increment my backpack counter to 1. Next time you run me with, I dont know, anything 10, 11, whatever, with 10, check my backpack first.

[00:01:51] Counter says 1, return out, sorry I can only be run once, I've clearly been run one before, my function gets a memory. This means that you can do stuff like build a tic-tac-toe game but click the cell. You only wanna click once and you can't ever click it again, because the functions's being called already once, various situations like this.

[00:02:13] This turns out to be very useful in professional engineering, to onceify, to make a function only be allowed to be run once. That's one of your challenges by the way, very demanding challenge. All right, what about memoize? Well, memoize says well, hold on, supposed I build, as we said, nth prime.

[00:02:32] To the find the thousandth prime number, you've got to find all the prime numbers up to that as well. It's a complicated demanding task, it takes lots of steps, maybe two, three, four seconds. If you pass a thousand to nth prime, you don't want to have to, if you end up passing a thousand again to it, have to go and recalculate a thousand when you already ran a thousand in it a few seconds ago.

[00:02:55] So you memoize the function as such that, when you call it the first time with a thousand, you do all the hard work to find the thousandth prime number. You do all the sieve thing, anyone come from math, you do the sieve thing, whatever it is, I don't know how you do it.

[00:03:09] But you find the thousandth prime number and then yes, you return it out. Great, the function worked. But also, you have an object, in the backpack, let's call it store, and it's an object. And in there, you make a key a thousand, and you make a value the associated thousandth prime number from the time you just run it then.

[00:03:32] Next time you run nth prime with the input of 1,000, you don't do all the hard work first, you go look in the backpack, look in the store. We already rounded a 1,000, we can just parse it one step out to the 1,000th prime number, all bundled up in our persistent cache on the back of our function, nth prime.

[00:03:51] This is very profound, very powerful. Our functions get to have little memories. Now, we can hold on to data in global memory. We could say like have counter is zero, but the problem with that, a couple of things. One, we want often independent live stores associated with each other function.

[00:04:10] You can imagine how good that is for modularizing our code. There you go. And another thing is, when we write code at scale, and this is where closure is particularly powerful. We do not want to, what's called pollute our global memory. You got 100 engineers work on the same team, 10,000s of lines of code and you've got a variable saying counter.

[00:04:34] This is not realistic, someone else wants to call their variable counter. You got one saying results. I promise you, someone else on the team wants to call their variable results. But you gotta hold on to data. Suppose you got a game, you want player one's score not to be gone.

[00:04:52] You need to have player one equals 20, but it gets super complicated. You don't necessarily want to taint the global name space. You don't wanna put that counter 2, counter 4 here, so what do you do? Well, one option is, use what's called the module pattern. And the module pattern in JavaScript says, If I store my data inside my function.

[00:05:16] But every time that function finishes running, the data is gone. But I wanna hold on to data, okay? Store it in global, but that's dangerous, cuz it can get overwritten really easily, is really hard to maintain. What if I wrote these functions in such a way, the way Katie said, that there were really easy to write to by parsing something in?

[00:05:36] That then, send off into the backpack and easy to get the data out of? What if I store the data I want to persist in the backpacks, on my functions?
>> Speaker 1: Therefore, for the life of my application, I have that data around but it's persisting in a very protected area.

[00:05:55] So I just write this function in a really clean way and then module pattern lets you do that, such that my data sticks around but I'm not polluting, tainting the global memory itself, and this is called the module pattern. That's advanced stuff, it lies even in Codesmith. I think it is week seven of Codesmith, it's very demanding stuff, the module pattern.

[00:06:18] But it is also super seasoned developer profession type of code writing. And that relies fundamentally on using our persistent lexical scope reference, our closed over variable environment, all same thing. Our closure, our backpack or our, did I say closed over variable environment, closed over, I said that one already?

[00:06:44] What's the other one? Closed over environment, persistent reference, closure, backpack, there you go. All those things, they all mean the same thing. There we go folks, that's it. At this point we have covered the end of day one. Thread execution context call stack, which gave us the foundations to tackle quite a lot harder stuff, right?

[00:07:03] You're sitting there thinking, I got what multiply by 2 does. But all those pieces gave us the pieces to handle higher order functions and then the most esoteric of JavaScript concepts, closure. All right, at this point, we wait until tomorrow to continue. Tomorrow we will handle asynchronous JavaScript and object oriented JavaScript.