Understanding how average of an array works

const arr = [1, 2, 3, 4, 5];

var sum = 0;
for (var number of arr) {
    sum += number;
}
average = sum / arr.length;
console.log(average);

Hi all, I have some questions about how this bit of JavaScript is working. I understand what it’s doing, but still have some questions.

  1. The use of var. My understanding is that it’s no longer best practice to use var and yet this code begins with const? Is this an oversight or is there a reason this was written this way?
  2. On the topic of declaring variable, why isn’t average preceded by const or let?
  3. Lastly how exactly does of interact with the variable number and the array?

As you’ve already noticed, it’s usually best to remain consistent with the use of const and var. I would either rename const to be var, or update the code so that it uses const and other techniques such as array reduce, to good benefit.

I can come back in a few hours with suitable details.

1 Like

When it comes to using const, I find it effective to replace all var with const, and take care of any issues from there. I’ll also use const with average, as currently that is being defined as a global variable which is best to be avoided.

The sum and the for loop cannot have const being used with that, as a reassignment of sum occurs, so let is used there instead.

const arr = [1, 2, 3, 4, 5];

let sum = 0;
for (let number of arr) {
    sum += number;
}
const average = sum / arr.length;
console.log(average);

It’s best to not use let though, as reassignment tends to lead to problems. Fortunately we have array methods such as map, filter, and reduce, to help with such tasks.

In this case the reduce method will benefit us here.

const arr = [1, 2, 3, 4, 5];
const sum = arr.reduce(function (total, number) {
    return total + number;
});
const average = sum / arr.length;
console.log(average);

And if more modern techniques such as arrow-notation are used, that can look like this:

const arr = [1, 2, 3, 4, 5];
const sum = (total, number) => total + number;
const average = arr.reduce(sum) / arr.length;
console.log(average);
2 Likes

It’s a good idea to provide an initial value with reduce. If you try it with an empty array it will throw an error.

Uncaught TypeError: Reduce of empty array with no initial value

fix

const average = arr.reduce(sum, 0) / arr.length;
1 Like

Thanks, I tend to rely on the default behaviour of reduce where with no initial value it instead uses the first item in the array.

1 Like

I always struggle about this “optimization”.
In my eyes, it is not consistent to the function itself but some strange special behavior just to make it possible to reduce typing a few characters.

I always struggle about this “optimization”.

What are you talking about specifically @Thallius . reduce vs the for loop? reduce(function(total, number)…)) vs reduce(sum)? or dropping the zero?

Sorry up most the night, so a bit sketchy :slight_smile:

No, I mean, that “magic” that reduce uses the first element of an array if there is no start value given.
In my understanding in the example of Paul

const sum = (total, number) => total + number;
const average = arr.reduce(sum) / arr.length;

I should get an “number is not defined” error.

1 Like

Actually you should expect to get NaN. (Javascript doesnt mind you adding numbers to Undefined, it just happily returns NaN as a result)

What actually happens is defined by the Javascript definition for the reduce function.

If the initial value of the accumulator is not specified (it would be a parameter after the function definition), the loop doesnt start at index 0; it instead starts at index 1, and uses the value of index 0 as the initial value for the accumulator. (This is why it throws an error if the array’s empty, because there isnt a 0th or 1st element of the array to use)

1 Like

I know that, and this is what I mean with “magic” “optimization”. I don’t like such “hidden features” which are not straight forward but only implemented because it shortens the code for a few characters.

Perhaps. But it was probably also implemented because of that above quirk of adding numbers to Undefined not being an error in Javascript.

@Thailius, I haven’t checked scala, haskel or lisp yet, but it does appear to be a standard implementation of reduce/fold, rather than just a javascript quirk.

php array_reduce

initial

If the optional initial is available, it will be used at the beginning of the process, or as a final result in case the array is empty.

python’s reduce (from the docs)

Roughly equivalent to:

def reduce(function, iterable, initializer=None):
   it = iter(iterable)
   if initializer is None:
       value = next(it)
   else:
       value = initializer
   for element in it:
       value = function(value, element)
   return value

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.