Closure is a powerful mechanism in JavaScript. To understand closure better, it helps to understand how lexical scoping works.
Lexical scoping, in essence, defines the scope of a variable relative to the position it was declared in the code.
For example :
So according to lexical scoping, scopes can be nested and inner function can manipulate and use the variable declared in its outer scope, like above.
Now that we know what is lexical scoping, another thing that helps us understand closure better is,
Higher-Order Functions : Functions are first-class citizens in JavaScript. To put it plainly, we can treat functions the same way we treat any other values. That is, we can store functions in variables, we can pass them as arguments and we can return them from functions.
One thing to note is that we only use () when we call a function. When we pass it as an argument or when we assign it to a variable, we do not use () with the function.
Now on to closure,
In JS a global variable can be used and manipulated anywhere, and local variables can only be used and manipulated inside their scope (i.e. function they are declared in). But in there are times when it is required for us to use a certain variable in the code, but at the same time be prevented from manipulating it. This is where closure comes in.
It allows a function to refer to variables, from outside its scope, inside it. Just like we have seen above. But the twist is, Closure helps preserve the outer scope in its inner scope, even after the function owning the outer scope has been executed.
Like we see above, we can access the message variable, but we have no way of changing its value.
It makes it possible for a function to have "private" variables.
So to make it simple,
Closure is when a function can access its lexical scope, even when that function is executing outside its lexical scope.
OR
Inner functions can access its parent scope, even after the parent function is already executed.
Closures is a simple yet very powerful concept in JavaScript. It might be a little tough to understand at first. But once you understand it, it opens up a lot of options and helps you understand a lot of things going forward, be it reading legacy code, or using it as good practice.
Another important concept that you will need to learn next is memoization. It is built on top of closure.