Почему при сумме двух значений типа Number на выходе получается NaN? JavaScript

Всем привет. Задача: написать на JavaScript функцию, которая считает сумму цифр числа. Например: число 1357, сумма 1 + 3 + 5 + 7 = 16, используя рекурсию. Через методы Array (reduce, shift) все работает. Написал не используя их - напрямую, по индексам такой код:

let num, newNum, sum, len;
num = (prompt('Num').split(''));
newNum = num.map(Number);
len = newNum.length;

function summ(newNum, len, sum) {
    sum = sum + newNum[len];
    return (len == 0) ? sum : summ(newNum, --len, sum);
}

alert(summ(newNum, len, sum = 0));

возвращает NaN

Мониторил через консоль выводом, через дебаггинг: sum += newNum[len] - на этом шаге переменная sum становится NaN хоть ты убей. Первая итерация - она Number (через typeoff смотрел), последующие - Nan. При этом newNum[len] - строго Number. Прямое приведение к Number в начале функции тож не помогает. В чем причина?


Ответы (1 шт):

Автор решения: Grundy

На первой итерации len == newNum.length

Свойство .length возвращает значение, которое больше самого большого индекса в массиве.

Поэтому при попытке взять элемент newNum[newNum.length] получается undefined.

Для решения достаточно убрать лишнее изменение переменной sum: sum = sum + newNum[len];

и сразу передавать это значение в параметр следующего вызова.

Пример:

let num, newNum, sum, len;
num = (prompt('Num').split(''));
newNum = num.map(Number);
len = newNum.length;

function summ(newNum, len, sum) {
  return (len == 0) ? sum : summ(newNum, --len, sum + newNum[len]);
}

console.log(summ(newNum, len, sum = 0)); 

Также стоит отделить параметры от глобальных переменных и перестать менять значения переменных, достаточно передавать новые значения в качестве параметров:

let num, newNum, sum, len;
num = (prompt('Num').split(''));
newNum = num.map(Number);
len = newNum.length;

function summ(arr, len = arr.length, sum = 0) { // значения по умолчанию
  return (len == 0) ? sum : summ(newNum, len - 1, sum + newNum[len - 1]);
}

console.log(summ(newNum));

→ Ссылка