Can you spot the bug in the following code?
// Compute the sum of the elements in array a
function sum(a) {
// Bonus feature: if we're passed more than one argument,
// then sum the arguments of the array instead.
if (arguments.length > 1) a = arguments;
var total = 0;
for(var i = 0; i < a.length; i++) total += a[i];
return total;
}
Hint: the function works correctly if you pass an array, but not if invoked with more than one argument.
Answer follows...
The problem with this code is that it doesn't take into account the very special behavior of the arguments array. Any change to a named argument becomes visible through the arguments array. And any change to an element of the arguments array is visible through the corresponding named argument. This is bizarre, but it is how it is supposed to work.
Now can you spot the bug?
Another hint: if you invoke sum(1,2,3), it returns the string "0[object Object]23".
Okay, the bug is in the first line. If there is more than one argument, then I want to sum the elements of the arguments array instead of summing the argument a. But I assign a = arguments. But changing a also changes arguments[0] because the arguments array is weird. So the first argument passed to the function has now been overwritten by the arguments array itself. If I had written the sum() method to recursively invoke itself on any array elements that were themselves arrays, this method would enter an infinite recursion, and the browser would hang until it ran out of stack space!
Here is a bug-free version of the code:
// Compute the sum of the elements in array a
function sum(a) {
var nums = a;
// Bonus feature: if we're passed more than one argument,
// then sum the arguments of the array instead.
if (arguments.length > 1) nums = arguments;
var total = 0;
for(var i = 0; i < nums.length; i++) total += nums[i];
return total;
}




Or just...
function sum(a) {
var total = 0;
for(var i = 0; i < arguments.length; i++) total += arguments[i];
return total;
}
...but that spoils the exercise ;-)
And it loses the special behaviour of summing the elements of an array if the array is all that's passed in. I would abbreviate this using a ternary, but it makes no real difference:
var nums = arguments.length > 1 ? arguments : a;
Interestingly the bug doesn't show up in Safari.