According to the definition provided by Wikipedia, this situation could be considered a closure:
A closure in programming is essentially a record that contains a function along with its associated environment. This environment includes a mapping of every free variable within the function (variables used locally but defined outside of it) to the specific values or references they had when the closure was created. Unlike a regular function, a closure permits access to these variables through copies of their values or references, even when the function is called outside of its original scope.
In the function test
, the variable a
is a free variable - utilized by the function without being internally defined. When the function is called outside of its block, it retains the value assigned to a
. Therefore, the essential characteristics of a closure, as per the Wikipedia definition, are met here.
Typically, closures involve defining a function within a certain environment and then exposing it by linking the function object to a name with broader reach. However, due to JavaScript's treatment of function declarations inside blocks, a similar effect is achieved in this scenario. While the function isn't explicitly exported, it still exhibits closure-like behavior thanks to how JavaScript handles block-scoped functions. Despite the absence of an explicit export mechanism, the set-up resembles a closure.
If you were to write:
{
let a = 'hi'
let test = () => a
}
test()
An error would occur. On the other hand, the following snippet works:
let b;
{
let a = 'hi'
let test = () => a
b = test
}
b() // "hi"
Therefore, the block essentially acts as a non-local environment capable of capturing variables. In essence, it may be acceptable to refer to this setup as a closure since it behaves like one, despite deriving from a pre-ECMAScript 2015 implementation that allowed relatively flexible handling of function declarations within blocks. If it resembles a duck, it might as well be one.