I'm working on a problem that requires a recursive function and have noticed that nested executions seem to be modifying the parent's parameters:
var foo = function(ar) {
console.log('Calling function - Array: ' + ar.toString());
if(ar.length > 1){
var ele = ar.pop();
foo(ar);
console.log('Function recursion ends - Array: ' + ar.toString() + ' Popped: ' + ele);
return;
} else {
console.log('Function ends - Array: ' + ar.toString());
return;
}
}
foo([1,2,3]);
outputs (indentation mine):
/* Calling function - Array: 1,2,3 Calling function - Array: 1,2 Calling function - Array: 1 Function ends - Array: 1 Function recursion ends - Array: 1 Popped: 2 Function recursion ends - Array: 1 Popped: 3 <-- What happened to 2? */
This seems odd - because I've invoked the function with [1,2,3]
and I'd expect the first iteration of the function to still maintain all of the elements provided to it between both ar
and ele
- but instead when the function concludes, only 1
remains in the provided array - what happened to 2
? Did the nested execution pop
it out of the first execution's variable?
My understanding of function scope in JavaScript would say that variables passed to a function can only modify them locally and do not export them back to the global/parent's scope as seen here:
var bar = 'bar';
function doBar(bar){
bar = 'foo';
}
doBar(bar);
console.log(bar); //Outputs 'bar';
But the output from the recursive function seems to challenge that understanding.
How can I prevent these nested executions from modifying the parent's parameter to bring back the missing 2
? Is my understanding of scoping in JavaScript wrong?
In my pathetic attempt to grasp at straws before opening this question, I've tried executing the function within a closure:
var foo = function(ar) {
console.log('Calling function - Array: ' + ar.toString());
if(ar.length > 1){
var ele = ar.pop();
(function(foo, ar){
foo(ar);
})(foo, ar)
console.log('Function recursion ends - Array: ' + ar.toString() + ' Popped: ' + ele);
return;
} else {
console.log('Function ends - Array: ' + ar.toString());
return;
}
}
But I got the same results as without using the closure - I suspect because I explictly passed in ar
and foo
making it no different than without the closure.