Check out a free preview of the full A Practical Guide to Algorithms with JavaScript course
The "Memoization with Closure Solution" Lesson is part of the full, A Practical Guide to Algorithms with JavaScript course featured in this preview video. Here's what you'd learn in this lesson:
Bianca walks through the Memoization with Closure Exercise to show how to use a closure to make the cache local. Bianca answers questions from students.
Transcript from the "Memoization with Closure Solution" Lesson
[00:00:00]
>> Bianca: Okay, so we're coming back from our third task related to memoization. Our goal here was to clean up our global scope by moving our cache inside of our function. This requires us to return a function from our memoizedClosure ten times function so that we could call it later.
[00:00:19]
What this does is it allows us to have a local version of our cache that, one, isn't reset every single time it would call the function that we're concerned about, and it doesn't clutter our global scope. As you can imagine, if you had this global cache, and you have multiple functions Interacting with this, it can have unexpected results.
[00:00:46]
And so, in general, that's why we like to avoid having global caches, and so this is a better approach is to have our local cache here. But it does require a little more expertise in JavaScript, in particular, being comfortable with returning function from functions and then calling them later.
[00:01:05]
So, this is called using a closure, and let's walk through how this works. The first thing we're gonna do here is we're gonna call this function, it's called memorized closure times ten. Very long name, and what this does is we are going to. Since we called it, we're gonna hop into the function body.
[00:01:29]
We're gonna initialize this cache as an empty object, and then we're gonna return this function, so this function now is referenced here. We could just take a peek at what this looks like, so again, call this function, this variable is just gonna save whatever this function returns. But what does this function return?
[00:02:01]
Another function, let's take a look of what that looks like. Here's memo closure times 10, which is just referring to our function, right? Which is awesome because that means that we can call it again, but what happens when we call it again? The first thing that we could do, let's pass nine to it, so when we call this function it's important to note that we're not calling the entire body of the memorized closure times ten folder function.
[00:02:36]
We're actually calling the body of the function that is being returned, it's an important distinction. So, when we call this function, we're hopping into the body of this one. Luckily, because of how closures work, we still have reference to variables declared in the parent scope. What is the parent scope?
[00:02:59]
Just this bigger function body, and also anything that's in the Globescope as well, we have reference to. We're going to pass 9, n is 9, we're going to check if, n is in the cache. Very first time we call it we know that we don't have anything in the cache so this is going to be undefined.
[00:03:15]
So we're going to skip down to our next block And we're gonna calculate our result. So our result is just n times 10. And we are going to save that into a variable. And then we are going to save that value into our cache object, just like before.
[00:03:34]
And then we're going to return the result, because We really care about that 90. We're not so worried about how it's implemented in the background. So our expected output is always 90 despite whether it's cached or not.
>> Speaker 2: Why would we pass an argument to the parent function?
[00:03:56]
Meaning that, why don't we have, I can't see the line, but const closure times ten equals closure times ten. Why don't we pass something there and then it becomes an argument in the function it's calling? And then we'll reference and return that. Why does it only go into the
[00:04:14]
>> Bianca: You could. So you could do that, so you can pass things here, you know you could pass numbers here and then you can call this M and you could do work on M and you could also reference M in this function and have access to it cause that's how a scope works or in this case at least.
[00:04:33]
So you could do that the reason that we're not doing that in this case Is because we wanna create a new function that we can use multiple times. And so this one we can use multiple times, we'll just pass an int. And the only point of our parent function is to make this cache variable private.
[00:04:51]
That's the only reason that we're doing that is because we want to take our cache object out of the global scope Put it inside of a function so then it's private to that function scope. Also, what we can do is if we call this again, we can have two separate caches, okay?
[00:05:12]
So, for example, if, let's say
>> Bianca: Let's say that, okay I'm gonna do it. I'm gonna do it. Let's say that we want this to be generic, okay? And then we would call this memoize closures closure times m. Okay we pass m This one is gonna be ten, okay?
[00:05:43]
Following here so we name this for calling it with in ten in this ten
>> Bianca: and the we return this function, now this function is always gonna return N times M. So that's what we're gonna call this, memoClosureTimes10, because n is 10. However, we could also do something like this.
[00:06:07]
>> Bianca: 5, now every time we call this function it's still cached but we're multiplying n times 5 now. And so every time you call a function, you create a new execution environment. And inside that execution environment, you have your local variables, and you can do really cool stuff with it.
[00:06:29]
This is the power of a closure, is that even though it's kinda confusing, cuz you're returning functions, and here's this other function It's very very powerful, and it allows you to make generic functions. And it really is the underlying technique that powers the functional programming paradigm.
>> Bianca: Cool, but we're not doing that, we're just doing Like this, so that's kinda cool.
[00:07:03]
>> Bianca: And anyway,
>> Bianca: The reason again, so the point I wanna make here is, the reason that we can even call this, like this, we have our invocational operator, is because we're returning a function. If you get the error like undefined is not a function, then you know that you're not returning a function.
[00:07:25]
I would check what your function is returning and make sure that you're actually returning function and not some primitive value. Or another thing that some people accidentally do is they will call the function. First and then return that, which is returning the result of the function that's called.
[00:07:40]
Does make sense? Versus the entire function body. Key here is this a function definition? This is a function invocation, and they mean different things, one is data, right so this function here's is just data we can return it like a string And this is a function invocation. This is an action, so this means run the body of this function.
[00:08:03]
And then afterwards, whatever that returns, you're gonna save it here. Anyway, that's our solution. Any questions? Everyone's like so many questions. Sorry, let me get this in frame. Yeah.
>> Speaker 3: So what would happen, and maybe just, I just need to know more about closures.
>> Bianca: Mm-hm.
>> Speaker 3: But what would happen if you were to do memo closure times nine comma.
[00:08:38]
8. And then, I just, I'm missing the portion where, why does it kind of know that we want 9 to 7 for n, if we are not giving it any sort of.
>> Bianca: We are giving it right here.
>> Speaker 3: Yeah, yeah. But then.
>> Bianca: Since this is just a function, we can call it multiple times.
[00:09:00]
And each time it could be different.
>> Speaker 3: What happens if you try to do two different arguments.
>> Bianca: Hmm.
>> Speaker 3: Does that work?
>> Bianca: Like this?
>> Speaker 3: Yeah.
>> Bianca: So to pass a second argument you would need to reference it here. You could do that, you would just need to be sure when you're defining, The, the function definition that your referencing that either by passing it like [INAUDIBLE] explicitly or you can do something like more generic or you're doing like that or you're doing like that or you're just gather all the rest into an array, that's another technique.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops