A closure combines a function together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
When a function is defined, it remembers its lexical scope, which includes all the variables in the scope where the function was defined. This information is stored internally as part of the function's closure.
If a function returns another function (inner function), the returned function carries with it its own code along with a reference to the scope in which it was defined. This combination of function code and the captured environment forms a closure.
When the inner function (closure) is executed, it has access to its own local variables, arguments, and also the variables from the scope in which it was defined. This access is possible because the closure retains a reference to its original lexical environment.
When the closure attempts to access a variable, it first looks within its own local scope. If the variable is not found there, it continues to look in the outer scopes, following the chain of lexical environments all the way to the global scope if necessary. This chain of environments is known as the 'scope chain.'
Closures only retain references to the variables they actually need. Any variables that the closure references, will not be garbage collected as long as the closure itself is still reachable. This is why closures can keep the values of variables alive even after their outer function has finished executing.
Closures exist as long as there is at least one reference to them. If a closure is stored in a variable, object property, or is passed as an argument to another function, it will remain in memory. However, if all references to a closure are removed, it becomes eligible for garbage collection.