Tanveer Sayem / 2022-11-17
7 min read
const users = ['Rahim', 'Shafique', 'Rafique']; let name = 'Rafique'; const user = users.filter(user => user.startsWith(name));
user => user.startsWith(name)
is itself a function. It uses the name
variable. But name
is defined outside of the function. This is closure.greeting
function, where we declare variable name
inside it and then print it out.But what if we want our variable to be easily changable. So, we can actually do that by simply moving thefunction greeting() { let name = 'Rahim'; console.log(`Hello! ${name}`); } greeting(); // Logs 'Hello! Rahim'
name
variable outside of the greeting
function.
This lets us change thelet name = "Rahim"; function greeting() { console.log(`Hello! ${name}`) }
name
variable anytime from the outside of the function.
In other words, thegreeting(); // Logs 'Hello! Rahim' name = 'Shafique'; greeting(); // Logs 'Hello! Shafique'; name = 'Rafique'; greeting(): // Logs 'Hello! Rafique';
name
variable is no longer local to our greeting
function, but our greeting
function still have acces to the outer variable. Function have access to outside variables. Stop for a seccond and make sure you have no problem with this idea. Once this makes sense mode onto the next section.
It does not matter what the above does, but let's assume we want to run it twice. One way to do it would be to copy and paste it:/* A snippet of code */
Another way to do it would be to use a loop:/* A snippet of code */ /* A snippet of code */
The third way which we're particularly intereseted in today, is to nest it in a function:for(let i = 0; i < 2; i++) { /* A snippet of code */ }
Using a function gived us the ultimate flexibility because we can run this function any number of times, at any time - and from anywhere in our program. We can also call our new function only once if wanted to.function doIt() { /* A snippet of code */ } doIt(); doIt();
Notice how the above code is equivalent to the original code snippet:function doIt() { /* A snippet of code */ } doIt();
In other words, if we take some piece of code, “nest” that code in a function, and then call that function exactly once, we haven’t changed what that code is doing. There are some exceptions to this rule which we will ignore, but generally speaking this should make sense. Sit on this idea until your brain feels comfortable with it./* A snippet of code */
We will nest this whole example into a function, which we're going to call once:let name = "Rahim"; function greeting() { console.log(`Hello! ${name}`) } greeting();
function startADay() { let name = "Rahim"; function greeting() { console.log(`Hello! ${name}`) } } startADay();
greeting
function is inside the startADay
function. Is that even allowed? Can we really put a function inside another function?name
local variable. It also contains an greeting
function. Then it calls that greeting
function. Because greeting
is inside of startADay
, it “sees” all of its variables. This is why it can read the name variable.greeting
) reads or writes a variable (such as name) that is declared outside of it (such as in startADay
). const users = ['Rahim', 'Shafique', 'Rafique']; let name = 'Rafique'; const user = users.filter(user => user.startsWith(name));
const users = ['Rahim', 'Shafique', 'Rafique']; let name = 'Rafique'; const user = users.filter(function(user) { return user.startWith(name); })
Here,function startADay() { let name = 'Rahim'; function greeting() { console.log(`Hello! ${name}`); } setTimeout(greeting, 5000); } startADay();
name
is a local varaible inside the startADay()
function call. It's tempting to think it "disappears" after we exit startADay
, and it won't come back to haunt us.startADay
we tell the browser to call greeting
in five seconds. And greeting
reads the name
variable. So the JavaScript engine needs to keep the name
variable from that particular startADay()
call available until greeting
has been called.
In that sense, we can think of closures as of “ghosts” or “memories” of the past function calls. Even though our startADay()
function call has long finished, its variables must continue to exist for as long as the nested greeting
function may still be called. Luckily, JavaScript does that for us, so we don’t need to think about it.
user => user.startsWith(name)
has an “open binding”. In other words, it is clear from it what the user
is (a parameter), but it is not clear what name
is in isolation. When we say “actually, name
refers to the variable declared outside”, we are “closing” that open binding. In other words, we get a closure.Get emails from me about web development, tech, and early access to new articles.