Lodash _.sum() method
What you’ll learn
- How
_.sumis implemented as(array && array.length) ? baseSum(array, identity) : 0—why it’s a one-liner with surprising edge cases. - The friendly empty-input guard:
_.sum([]),_.sum(null),_.sum(undefined)all return0. - The string-concatenation trap: a single string in the array can turn the result into a concatenated string.
- How
baseSumskipsundefinedelements, coercesnullto0, and letsNaNpoison the result. - That
_.sumworks with all-BigInt arrays but throws on mixed BigInt/Number, and never fixes floating-point precision.
Prerequisites
Take a quick look at _.add() (pairwise) and _.mean() (which shares baseSum). Knowing how the + operator coerces strings vs numbers will save you a lot of head-scratching.
- JavaScript
+coercion: if either operand is a string, the result is a string. This is what makes_.sum([1, "2"])behave unexpectedly. - Float arithmetic:
0.1 + 0.2 !== 0.3. Lodash does not correct this.
Overview
The whole source is: function sum(array) { return (array && array.length) ? baseSum(array, identity) : 0; }. baseSum walks the array and, for every element where iteratee(value) !== undefined, runs result === undefined ? current : (result + current). That single line of logic explains every quirk on this page: the first non-undefined value seeds the accumulator without coercion, subsequent values are folded with native +, and undefined is silently skipped.
Empty → 0
Length-check guard: empty array, null, and undefined all return 0.
String poisoning
A single string in the array switches + to concat. The result becomes a string, not a number.
No precision fix
_.sum([0.1, 0.2, 0.3]) is 0.6000000000000001. Lodash just wraps native +.
Syntax
_.sum(array) - array (Array): the array to iterate over.
- Returns (number): the sum.
0for empty,null, orundefinedinput. May be a string if any element is a string (see Example 2). May beNaNif any element isNaN. - Want a key/iteratee? Use _.sumBy() instead—
_.sumtakes no second argument and silently ignores it.
Basics — clean arrays and the empty guard
The docs example, a few common shapes, and the friendly empty-input behaviour. Notice that null and undefined arrays don’t throw the way native reduce would.
import sum from "lodash/sum";
console.log(sum([4, 2, 8, 6])); // 20 (docs example)
console.log(sum([1, 2, 3, 4, 5])); // 15
// Floating-point reality: Lodash does NOT fix precision
console.log(sum([0.1, 0.2, 0.3])); // 0.6000000000000001
// Friendly guard for missing input
console.log(sum([])); // 0
console.log(sum(null)); // 0
console.log(sum(undefined)); // 0
// Larger array via Array.from + range
const ints = Array.from({ length: 100 }, (_, i) => i + 1);
console.log(sum(ints)); // 5050 The string-concatenation trap
Because baseSum uses native +, a single string is enough to flip the entire operation from arithmetic to concatenation. The result’s type changes too—you get back a string, not a number. Coerce with Number() or arr.map(Number) before calling.
import sum from "lodash/sum";
// String poison: one string flips '+' to string concat
const dirty = [1, "2", 3];
const total = sum(dirty);
console.log(total); // "123" (string!)
console.log(typeof total); // "string"
// Single-string array passes through unchanged (no coercion happens)
console.log(sum(["42"])); // "42" (still a string)
// null coerces to 0, undefined is silently skipped
console.log(sum([1, null, 3])); // 4
console.log(sum([1, undefined, 3])); // 4
// NaN poisons everything
console.log(sum([1, NaN, 3])); // NaN
// Fix: coerce to numbers first
console.log(sum(dirty.map(Number))); // 6
// Caveat: Number("oops") is NaN, which still poisons. Filter junk first if needed. Infinity, BigInt, and array-likes
A grab-bag of edge cases that matter in production. Infinity propagates, opposite infinities give NaN, BigInt works only when every element is a BigInt, and _.sum happily accepts array-likes with a length.
import sum from "lodash/sum";
// Infinity propagation
console.log(sum([1, Infinity, 2])); // Infinity
console.log(sum([Infinity, -Infinity])); // NaN
// Overflow to Infinity
console.log(sum([Number.MAX_VALUE, Number.MAX_VALUE])); // Infinity
// BigInt: works when ALL elements are BigInt
console.log(sum([1n, 2n, 3n])); // 6n
// Mixed BigInt + Number: throws
try {
console.log(sum([1n, 2]));
} catch (err) {
console.log("Threw:", err.message); // "Cannot mix BigInt and other types..."
}
// Array-likes work too (length-based iteration)
console.log(sum({ length: 3, 0: 10, 1: 20, 2: 30 })); // 60
// Common reporting helper
const orders = [
{ id: 1, total: 49.99 },
{ id: 2, total: 12.50 },
{ id: 3, total: 30.00 }
];
console.log(sum(orders.map(o => o.total))); // 92.49
// (Or use _.sumBy(orders, "total") in one call.) 📋 _.sum vs native alternatives
| Input | _.sum(arr) | arr.reduce((a,b) => a+b, 0) | Notes |
|---|---|---|---|
[4, 2, 8, 6] | 20 | 20 | Identical. |
[] | 0 | 0 | Both return 0. |
null / undefined | 0 | throws | Lodash adds a friendly guard; reduce needs ?. or a null-check. |
[1, "2", 3] | "123" (string) | "0123" (string) | Both poisoned by string concat. The reducer’s seed 0 still concats once a string arrives. |
[1, undefined, 3] | 4 | NaN | Lodash skips undefined; reduce does 1 + undefined. |
[1, null, 3] | 4 | 4 | Both treat null as 0. |
[0.1, 0.2, 0.3] | 0.6000…1 | 0.6000…1 | Same float-precision result. |
[1n, 2n, 3n] | 6n | throws on seed 0 | Lodash seeds with the first element (BigInt). The reducer needs a BigInt seed (e.g. 0n). |
Pitfalls to avoid
One string poisons the sum
_.sum([1, "2", 3]) returns "123", not 6—and the type changes to string. Coerce with arr.map(Number) before summing if the data is untyped.
Poisons everything
A single NaN turns the sum into NaN. Filter with arr.filter(Number.isFinite) first if junk values are possible.
Not a precision fix
_.sum([0.1, 0.2]) is 0.30000000000000004. The old reference’s “use Lodash for financial calculations” framing is misleading—scale to integer cents (or use decimal.js) for money.
No iteratee, silently ignored
_.sum(orders, "total") ignores the second argument and sums the array’s objects—giving you a useless string. Use _.sumBy().
All-or-nothing
All-BigInt arrays work and return a BigInt. Mixing with Number throws Cannot mix BigInt and other types.
❓ FAQ
Summary
- Purpose: add every value in an array—
baseSum(array, identity)when non-empty,0otherwise. - Remember: empty/null/undefined →
0;undefinedelements skipped;null→0; one string poisons to concat;NaNpoisons; all-BigInt works (mixed throws); precision unfixed. - Next: Lodash _.sumBy(), or read the official Lodash docs for _.sum.
_.sum([]) returns 0—not NaN like _.mean([]). Lodash short-circuits with (array && array.length) ? baseSum(array, identity) : 0, so empty arrays, null, and undefined all give back the same friendly 0. The flip side: a single string poisons the result—_.sum([1, "2", 3]) returns the string "123", not 6.
6 people found this page helpful
