I was trying to comprehend the behaviour of Javascript and recursive programming.
Npw, I am sort of beginner so I need to understand why do I get already have been declared error and when I don’t get already have been declared error
Consider this code, I was trying to understand how this will execute..
let company = { // the same object, compressed for brevity
sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 600 }],
development: {
sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
internals: [{name: 'Jack', salary: 1300}]
}
};
// The function to do the job
function sumSalaries(department) {
if (Array.isArray(department)) {
return department.reduce((prev, current) => prev + current.salary, 0);
} else { // case (2)
let sum = 0;
for (let subdep of Object.values(department)) {
sum = sum + sumSalaries(subdep);
}
return sum;
}
}
console.log(sumSalaries(company));// 6700
Breaking the execution of the above code (correct if I am understanding this wrong)
- We are passing company as an argument to sumSalaries
- Inside sumSalaries, we are checking if it is an array or not
Intitally it is not an array since company is an object above.
- We will pass it else condition with declaration of let sum = 0
- object.values will give us two arrays (based from company)
- In the first iteration of
let subdep of Object.values(department
, we will get
[{…}, {…}] inside which we have following object {name: "John", salary: 1000}
- Here our sum = 0, we will add our sum with return of what we passing to
sumSalaries(subdep);
-
Now since we are passing the array, it will go to following function
if (Array.isArray(department)) {
return department.reduce((prev, current) => prev + current.salary, 0);
} -
Her in our previous we are passing 0 and adding it with current.salary.
- Since we are using reduce, hence it will first add
0 + 1000
and then it will add1000 + 600
- This will return us 1600 and hence our
sum
would be 0 + 1600 - Now our loop will do second iteration, which gives us an object consisting of two arrays …
- Since it is an object, It won’t pass into
if (Array.isArray(department)) {
and go toelse
instead
Problem + Question
While, I was completing the thirteen point, I realised that our second declaration have let sum = 0
So, Two things
-
Since we have
let sum = 0
, shouldn’t there be an error stating that let sum already exsist -
Either way, we are doing sum = 0, does that mean our previous value (
1600
) in the sum array is gone (or in other words reset to zero?
In javascript, a function is, in essence, a scope.
Recursive calls of the same function will also be independent scopes. The variable sum
declared in the previous recursive function call will not be the same as the one declared on the next.
You’ll only get the
Identifier has already been declared
if you declare the variable twice in the same scope.
Each time you call a function, it creates a new space (usually called ‘scope’ or ‘stack-frame’) to hold all the variables declared inside of it.
Variable-already-declared errors only show up when you declare the same variable twice in the same space
Because the ‘sum’ variables created inside the first call to sumSalaries and the second (recursive) call are in different spaces, there’s not going to be an error.
let
is block scoped, which means having multiple declarations in multiple blocks is okay. Each time you call sumSalaries()
the sum
will be reset to zero. It doesn’t need to remember previous calls because it will return the sum if finds for this call which, as the recursion unwinds, will be added to the parent who called the recursive function.
It can be instructive to watch the recursion with strategically placed, console.log()
calls or by using a debugger. For example you can watch the sum add up with:
let company = { // the same object, compressed for brevity
sales: [{name: 'John', salary: 1000}, {name: 'Alice', salary: 600 }],
development: {
sites: [{name: 'Peter', salary: 2000}, {name: 'Alex', salary: 1800 }],
internals: [{name: 'Jack', salary: 1300}]
}
};
// The function to do the job
function sumSalaries(department) {
if (Array.isArray(department)) {
return department.reduce((prev, current) => prev + current.salary, 0);
} else { // case (2)
console.log("starting new object")
let sum = 0;
for (let subdep of Object.values(department)) {
let subsum = sumSalaries(subdep)
console.log("subsum = ", subsum)
sum = sum + subsum;
}
console.log("current sum:", sum)
return sum;
}
}
console.log(sumSalaries(company));// 6700