TL; DR, установите начальное значение
Используя Разрушение
arr.reduce( ( sum, { x } ) => sum + x , 0)
Без разрушения
arr.reduce( ( sum , cur ) => sum + cur.x , 0)
С машинописным шрифтом
arr.reduce( ( sum, { x } : { x: number } ) => sum + x , 0)
Давайте попробуем метод деструктуризации:
const arr = [ { x: 1 }, { x: 2 }, { x: 4 } ]
const result = arr.reduce( ( sum, { x } ) => sum + x , 0)
console.log( result ) // 7
Ключом к этому является установка начального значения.Возвращаемое значение становится первым параметром следующей итерации.
Техника, используемая в верхнем ответе, не является идиоматической
В принятом ответе предлагается НЕ передавать «необязательное» значение.Это неправильно, так как идиоматический способ заключается в том, что второй параметр всегда должен быть включен.Зачем?Три причины:
1.Опасно - Не передавать начальное значение опасно и может создать побочные эффекты и мутации, если функция обратного вызова небрежна.
Вот
const badCallback = (a,i) => Object.assign(a,i)
const foo = [ { a: 1 }, { b: 2 }, { c: 3 } ]
const bar = foo.reduce( badCallback ) // bad use of Object.assign
// Look, we've tempered with the original array
foo // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
Если, однако, мы сделали это таким образом, с начальным значением:
const bar = foo.reduce( badCallback, {})
// foo is still OK
foo // {a:1,b:2,c:3}
Для записи всегда присваивайте это Object.assign({}, a, b, c)
,Установите первый параметр для пустого объекта {}
2 - лучший вывод типа - При использовании инструмента, такого как Typescript, или редактора, такого как VS Code, вы получаете возможность сообщитькомпилятор инициала, и он может отлавливать ошибки, если вы делаете это неправильно.Если вы не установите начальное значение, во многих ситуациях его невозможно будет угадать, и вы можете получить жуткие ошибки времени выполнения.
3 - Уважение к функторам - JavaScript светит лучше, когда его внутренний функциональный дочерний элемент освобожден.В функциональном мире существует стандарт того, как вы «складываете» или reduce
массив.Когда вы складываете или применяете катаморфизм к массиву, вы берете значения этого массива для создания нового типа.Вам нужно сообщить результирующий тип - вы должны сделать это, даже если последний тип - это тип значений в массиве, другом массиве или любом другом типе.
Давайте подумаем об этом по-другому.В JavaScript функции могут передаваться как данные, как работают обратные вызовы, каков результат следующего кода?
[1,2,3].reduce(callback)
Будет ли возвращаться число?Объект?Это делает его более понятным
[1,2,3].reduce(callback,0)
Подробнее о спецификациях функционального программирования здесь: https://github.com/fantasyland/fantasy-land#foldable
Еще немного фона
* reduce
метод принимает два параметра:
Array.prototype.reduce( callback, initialItem )
Функция callback
принимает следующие параметры
(accumulator, itemInArray, indexInArray, entireArray) => { /* do stuff */ }
Когда предоставляется initialItem
, он передается как accumulator
в *Функция 1087 * в первом прошлом, а itemInArray
- первый элемент в массиве.
Если initialItem
не установлен, reduce
принимает первый элемент в массиве как initialItem
и передаетвторой пункт как itemInArray
.Это может сбивать с толку поведение.
Я учу и рекомендую всегда устанавливать начальное значение снижения.
Полный текст статьи по Array.prototype.reduce
см .:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Надеюсь, это поможет!