tl;dr
- according to ECMAScript, the complete lexical environment is bound
- in practice, engines optimize this if possible by binding only the used variables
- the optimization is not possible for example when
eval()
is being used inside
I found a great article series where this is discussed in-depth:
The articles are quite old but still valid, which you can verify by yourself (see below).
For your example: in theory someValues
would be bound (and not garbage collected) although it's not used in the record.getPrice
closure. But in practice only the variable you use there (sum
) is bound. And the fact that sum
is bound has no effect on the binding of someValues
, because sum
is derived from someValues
, but needs no further reference to it (it's a different thing it had been defined as const sum = () => _.sumBy(someValues, 'total')
)
Verfication: execute the following in the browser console:
(() => {
//eval(); // <- uncomment this line for second test
const thisIsUsed = 1;
const isThisBound = 2;
return () => {
debugger;
return ('result: ' + thisIsUsed);
}
})()();
When the debugger kicks in, take a look at the "Scope" (Chrome). You could also add thisIsUsed
and isThisBound
to the "Watch" list.
Here's a screenshot using Chrome (Canary, version 85.0.4154.0):

The same behavior can be observed with a current Firefox (version 76.0.1).
According to Dmitry Soshnikov's articles, eval()
can break the optimization. This is easy to understand as the engine then to assume that any variable may be accessed. This behavior can also be verified, just uncomment the line in the code sample above.