This article presents shortly what is the closure concept in Javascript, it also applies to other programming languages.
I write this article because I recently read an article that clearly shows a misunderstanding about the concept.
I am first going to present functions, then closures.
When you write code you usually write functions that you call at several places in your application.
Functions are useful if they can do something that is different based on the context: arguments you pass.
What is going on about "passing arguments"?
Imagine you are talking to someone, function, you give your name. That person knows your name, he/she could think about you but cannot change your name.
Now, imagine you give to someone a bag containing some candy. You wait as long as that person has your bag, he/she can take some candy or add anything.
In both cases you give something to someone but that person cannot do the same thing with "it".
The same applies to programming (the explanation here is for ´Javascript` but could be different in other programming languages).
function say(you) {
console.log("Hello", you);
you.replace("mes", "y");
console.log("Hello again", you);
you = "Me";
console.log(you);
}
let you = "James";
say(you);
console.log(you);
Here we define a function named say
, the function first outputs the value it receives (A) then calls the replace
function, outputs it again and it is unchanged (B).
It then does you = "Me"
, outputs and now we see "Me" (C).
After the call, the output shows that the you
is unchanged (D).
The reason why (B) is unchanged is that strings are immutable, I mean the value cannot be changed, so replace
does not change the string, it creates a new one.
At (C) and (D), the you
thing is just a way to "communicate with the programming language", it means "from now on when I say 'you', I mean 'James'". The sentence you = "Me"
in the say
function means "BTW, from now on when I say 'you', I mean 'Me'" (heu).
The say
function communicates with the language using the same name (you
), but the you
from the caller is caller's own way to give a name to "James".
It's like when James talks to me, he says "you" (caller), but when I hear someone in the train saying "you", I know it's not me 😉 (the say
function).
What about the bag...
function yoursForAWhile(bag) {
bag.pop();
bag.push("Jelly beans");
}
let bag = ["Chocolate", "Gumdrops"];
yoursForAWhile(bag);
console.log(bag);
Here the yoursForAWhile
function receives a bag (a Javascript array), it first removes something from the bag (pop
) (E), then adds something (push
) (F). When the caller gets back and outputs the bag content, the bag does not contain "Grumdrops" anymore... the bag is not immutable.
Closure has nothing to do with passing arguments, it is a place where you know about something.
Imagine you are sitting in a café, in front of you, you see an empty table. A while later some people come at that table, you see them, because you know about the table, nobody gave you the information.
let you = "James";
function say() {
console.log("Hello", you);
you = "Me";
console.log(you);
}
say();
console.log(you);
you = "Mary";
say();
The code here looks very similar to the previous one (the first example) but the difference is huge.
First, the say
function does not expect any parameter hence the call say()
. Next, giving the name you
to refer to "James" happens before the function definition, this way the function knows about it (the table in the café). This way both the caller and the function are talking about the same thing when they say you
.
Because they share the same knowledge, when the say
function does you = "Me"
it also affects caller's you
. And when I write from now on you
is "Mary" (you = "Mary
), the say
function outputs the new name when called again.
(getting back to the train, we are 3 buddies: James, Frank and I. When James tells me something using you
both James and Frank mean me 😉)