What Led Me to Reorganize This
Recently, I had an experiential intern interview at NAVER Webtoon.
It was my first interview, and maybe because I was nervous... I stumbled through my answers to CS-related questions.
One of them was a question about closures.
After coming home and thinking about it, I realized I had answered with misconceptions about closures.
To never make the same mistake again, I want to reorganize my understanding of closures.
The Etymology of Closure
In English, the word Closure is used in many different ways.
Looking it up in a dictionary, you'll find meanings like:
As the noun form of Close, it's used to mean closure, termination, end, closing, etc.
However, defining it only by dictionary meaning can easily cause confusion.
This is because the etymology of closure in JS is not based on the above, but originates from Closure meaning closed in mathematics and computer science.
Closure is commonly used in expressions like closed under ~.
For example, expressions like the set of integers is closed under addition or the set of integers has closure under addition are used.


In the case of Integer operations, even after performing arithmetic operations (+, -, *, /), the result still belongs to the set of integers.
When the result of an action returns to its own set, this is called Closure.
How is Closure Expressed in JS?

In JS, closures can be expressed as shown above.
The inner function inside the outer function references variable a within the outer function's scope from outside the outer function.
Various Expressions of Closures
Closure is not a concept unique to JavaScript.
It's a universal characteristic that appears in functional programming languages.

This is captured from the official Rust guide.
As you can see, Rust also handles closures.
Since it's not a concept unique to JavaScript, the ECMAScript specification doesn't cover the definition of closures either.
Not necessarily because of this, but various literature defines closures in their own ways.
Examining Through MDN's Definition
MDN defines closures as above.
Here, lexical environment refers to outerEnvironmentReference, one of the components of the execution context.
The scope, which is the valid range of variables, is determined by the environmentRecord and outerEnvironmentReference of LexicalEnvironment, enabling scope chaining.
Consider the point when the execution context of inner function B, declared in some context A, becomes active.
With code like above, function A cannot access variable b, but function B can access variable a.
This is because function B's outerEnvironmentReference references function A.
This is exactly what combination means.
However, the inner function B doesn't always reference function A's LexicalEnvironment.
If the inner function doesn't reference external variables, it can't be called a combination.
The combination, meaning the interaction with the lexicalEnvironment at the time of declaration, is only meaningful when the inner function references external variables.

Let's look at the diagram above again.
Based on what we've understood so far, Closure can be seen as "a phenomenon that only occurs in inner functions that reference variables declared in some function".
Examining Through Code
Let's look more closely through code.
Call Stack Flow in Normal Situations
The result of console.log(++a); on line 4, which is 2, is finally output.
When the execution context of the outer function ends, references to the identifiers (a, inner) stored in LexicalEnvironment are deleted.
Consequently, the values stored at each address have no variables referencing them, making them targets for garbage collection.
This is a diagram of the call stack and execution context with VariableEnvironment and ThisBinding omitted.
This is normal behavior inside a function, with no special phenomena.
Call Stack Flow in Situations Where Closures Occur
On line 6, the result of executing the inner function is being returned.
As a result, at the point when the outer function's execution context ends, there's nothing referencing variable a.
Like the previous example, the values of a, inner variables will eventually be destroyed by the garbage collector.
Up to this point, the inner function's execution context ends before the outer function's execution context ends.
Therefore, the inner function cannot be called separately.
The environmentRecord of the inner function's execution context has no information to collect.
The LexicalEnvironment at the location where the inner function was declared is reference-copied to outerEnvironmentReference.
Since the inner function was declared inside the outer function, the outer function's LexicalEnvironment is contained.
Following Scope Chaining, it accesses variable a declared in the outer function, increases it by 1, returns the value 2, and the inner function's context ends.
Line 10 similarly returns 3.
The Principle of the Garbage Collector
When the inner function's execution context becomes active, outerEnvironmentReference needs the outer function's LexicalEnvironment, so it's excluded from the collection target.
Thanks to this, the inner function can access variable a.
Understanding Call Stack Flow Through Diagrams
Summary
Earlier, I said that closure is a phenomenon that only occurs in inner functions that reference variables declared in some function.
Don't forget it's a phenomenon. A closure is not a function.
Recalling what we last looked at, here variable a belonging to the outer function's LexicalEnvironment was excluded from the target.
The only case where LexicalEnvironment is excluded from the garbage collector's collection target after the function's execution context ends is when an inner function that references local variables is passed to the outside.
"A phenomenon that only occurs in inner functions that reference variables declared in some function" means "a phenomenon where the outer function's LexicalEnvironment is not garbage collected".
Based on this, if we revise the definition, it becomes:

Let's look at the diagram again with this concept in mind.
Do you understand it now?
Precautions
Does passing to the outside only mean
return?
Let's look at it through code.
Local variables are referenced inside the handler function to be registered with the method (addEventListener) of a separate external object, DOM.
Both situations are closures because inner functions that reference local variables were passed to the outside.

