I have a misunderstanding: is the strainer function an example the downward funarg problem? I was using Chrome debugger under the "Sources" panel and noticed this under the "Scope" section:
Is the strainer function parameter cb
a closure or is the function strainer
the closure? I'm finding it difficult to sort through the information about closures and the funarg problem on the web. I clearly don't understand the funarg problem or closures and need some help.
function strainer(collection, cb) {
return collection.reduce(function inner(acc, curr) {
if (cb(curr)) {
return acc.concat(curr);
}
return acc;
}, []);
}
function even(number) {
if (number % 2 === 0) {
return true;
}
return false;
}
var collection = [1, 2, 3, 4, 5];
strainer(collection, even);
Background: I was under the impression private variables returned to an outer environment created closures but the example looks like something different.
The flintstones function example below has closure over the scope of the quotes function (I think this is the upward funarg problem).
function quotes() {
var x = 'yabba dabba doo!';
return function flintstones() {
return x;
}
}
var fredSays = quotes();
fredSays();
Is the strainer function param
cb
a closure or is the functionstrainer
the closure?
Neither, actually. inner
is the closure. You are inspecting the scope chain of inner
here - it has local acc
and curr
variables, and free variable cb
that closed over the cb
variable from the strainer
scope. That's what the debugger is trying to show you. The cb
part of the strainer
scope is not allocated on the stack but in the heap, however the debugger doesn't display that detail.
Yes, this is more or less the downward funarg problem. inner
is passed to reduce
here, and that's why we create a closure for it. Notice that the distinction between upward and downward is meaningless in JS, since we never know what the called function does with the passed callback - it might as well stow it away somewhere. Proving that it stays contained in and does not escape the call is not done.