When The JavaScript engine makes sure that the function has access to all the variables outside of the function, it’s a closure. closures are a feature in JavaScript also called lexical scoping. it’s a combination of 2 things: functions are first-class citizens and the lexical scope.
Lexical Scope
lexical means – where it is written,
scoping means – what variables we have access to.
It means that where we write the function matters and not where we invoke the function. before we run any code, the JavaScript engine already knows which function has access to which variables
First-Class Citizen
First-class citizen is a term that means that:
- Functions can be assigned to variables and properties
- Functions can be passed as arguments to another function (Higher Order Functions)
- Functions can be returned as values from another function (Higher Order Functions)
Functions are data, they not only perform actions but also data that can be passed around like first-class citizens, as if they were JavaScript types.
The idea of first-class citizen property in JavaScript introduces JavaScript to a world called “functional programming”.
Closures
Closures allow a function to access variables from the enclosing scope or outer environment, even after it leaves the scope in which it was declared.
Let’s see an example:
function a() {
const apple = 'apple';
return function b() {
const orange = 'orange';
return function c() {
const pear = 'pear';
return `I love to eat ${apple}, ${orange} and ${pear}`;
}
}
}
console.log(a()()()); // I love to eat apple, orange and pear
The function “c” holds the value of “apple” and “orange” variables even though the function “a” and b” have been invoked and finished which means that these functions have been removed from the call stack and from memory too. somehow the garbage collector skipped these variables.
The JavaScript engine recognized that there is a reference to variables “apple” and “orange” in the “c” function so the reference has been kept.
Let’s see another example:
function doGreeting() {
setTimeout(function() {
console.log(greet);
}, 1000);
const greet = "Hello There";
}
doGreeting(); // Hello There.
Even though the setTimeout has been sent to the Web API and waits in the queue before the variable have been created, by the time that the callback is sent to the call stack, the call stack is empty, and the function “doGreeting” already ran and the variable has been created and assigned.