Lodash _.mean() method

Beginner
⏱️ 6 min read
📚 Updated: May 2026
🎯 3 Code examples
🚀 3 Try-it labs
Lodash

What you’ll learn

  • How _.mean(array) is really baseSum(array, identity) / array.length—a thin wrapper, not a statistics engine.
  • That empty / null / undefined input returns NaN, not undefined (a common doc error).
  • The string-concatenation trap: one stray string and your average turns into garbage (34010, not 20).
  • How undefined elements are skipped from the sum but still counted in the length.
  • Three runnable labs (?tryit=1, 2, 3) covering the basics, the dirty-data trap, and the empty-array fix.

Prerequisites

Skim the Lodash Math hub and _.add() first. _.mean shares the same +-driven coercion quirks as the rest of the Math family—learn them once, they pay off everywhere.

  • How + works in JS: mixing in even one string flips arithmetic into concatenation.
  • NaN semantics: NaN === NaN is false; use Number.isNaN() or Number.isFinite().

Overview

The whole implementation is six lines of baseMean: length ? baseSum(array, iteratee) / length : NaN. baseSum walks the array, calling iteratee(value) (here _.identity), and runs a running result + current—skipping only elements where the iteratee returned undefined.

Sum then divide

No Kahan-style precision tricks—just + in a loop, then divide by array.length.

Length counts everything

Even skipped values (undefined) contribute to the divisor. null contributes 0 to the sum.

No type validation

Strings pass through and become concatenations. Sanitize input with .map(Number) before averaging untrusted data.

Syntax

javascript
_.mean(array)
  • array: array (or array-like) of numbers.
  • Returns: number—the arithmetic mean. NaN when the input is empty, nullish, or contains an element that poisons the sum.
  • Need an iteratee? Reach for _.meanBy(): same engine, with a per-element score function or property path.
1

Basics — clean numeric arrays

The happy path: integers, floats, and a single-element array. Note the floating-point result—Lodash does no precision rounding for you.

javascript
import mean from "lodash/mean";

console.log(mean([4, 2, 8, 6]));        // 5  (docs example)
console.log(mean([10, 20, 30, 40, 50])); // 30
console.log(mean([42]));                  // 42  (single-element)
console.log(mean([0.1, 0.2, 0.3]));      // 0.20000000000000004
console.log(mean([0.1, 0.2, 0.3]).toFixed(2)); // "0.20"
Try it Yourself
2

Dirty data — strings, null, undefined

This is where most bugs live. A single string element turns the running sum into a string, and the final divide produces a number that looks plausible but is nonsense (34010, not the 20 you expected). undefined entries get skipped from the sum but still count toward the length.

javascript
import mean from "lodash/mean";

console.log(mean([10, "20", 30]));        // 34010 — '1020' + 30 = '102030', then /3
console.log(mean(["10", "20", "30"]));    // 34010 — same trap

console.log(mean([10, undefined, 20]));   // 10  — sum 30, but length is 3
console.log(mean([10, null, 20]));        // 10  — null coerces to 0, divisor still 3
console.log(mean([10, NaN, 20]));         // NaN — NaN poisons everything

// Safe pattern: coerce + filter first
const dirty = [10, "20", null, "abc", 30];
const clean = dirty.map(Number).filter(Number.isFinite);
console.log(mean(clean));                  // 20
Try it Yourself
3

Empty / nullish input returns NaN

Many tutorials claim _.mean([]) is undefined. It isn’t—baseMean returns 0 / 0 when the array is empty or missing, which is NaN. Always guard before you display the result.

javascript
import mean from "lodash/mean";

console.log(mean([]));                                   // NaN
console.log(mean(null));                                 // NaN
console.log(mean(undefined));                            // NaN

// Pattern: default with Number.isFinite, not || or ??
function safeMean(arr) {
  const m = mean(arr);
  return Number.isFinite(m) ? m : 0;
}

console.log(safeMean([]));            // 0
console.log(safeMean([10, 20, 30]));   // 20

// Infinity propagates
console.log(mean([1, Infinity, 2]));    // Infinity
console.log(mean([Infinity, -Infinity])); // NaN
Try it Yourself

📋 _.mean vs native alternatives

Input_.mean(arr)arr.reduce((a,b)=>a+b,0)/arr.lengthNotes
[4, 2, 8, 6]55Identical happy path.
[]NaNNaN (0/0)Same result, but native reduce-without-init would throw.
[10, undefined, 20]10NaNLodash silently skips undefined; reduce includes it.
[10, "20", 30]3401034010Both fall to the string trap; neither validates.
[1n, 2n, 3n]throwsthrowsBigInt cannot mix with + on numbers.

Pitfalls to avoid

Dirty data

String concatenation

One stray string in the array silently converts + to string concatenation. The final divide makes the result look like a number, so the bug hides. Always .map(Number).filter(Number.isFinite) first when the data comes from JSON, forms, or CSV.

Empty arrays

It’s NaN, not undefined

Branch on Number.isFinite(result), not on result == null. NaN ?? 0 is still NaN—nullish coalescing does not catch it.

Skipping rules

Length still counts skipped slots

undefined elements are dropped from the sum but the divisor is still array.length. Filter them out yourself if you want them excluded from the count.

Precision

No rounding for you

_.mean is IEEE-754 like everything else. Apply .toFixed(n) or scale-round-unscale for display.

BigInt

Throws on BigInt input

_.mean([1n, 2n, 3n]) throws Cannot mix BigInt and other types. Convert to Number if you can afford the precision loss.

❓ FAQ

Neither—it returns NaN. baseMean returns 0 / 0 for any nullish or empty input. Always test with Number.isFinite() before using the result downstream.
You get 34010, not 20. baseSum uses +, which becomes string concatenation as soon as one operand is a string: 10 + '20' = '1020', '1020' + 30 = '102030', then '102030' / 3 = 34010. Coerce with .map(Number) first if your data is dirty.
undefined elements are skipped from the sum but still counted in length, so _.mean([10, undefined, 20]) is (10+20)/3 = 10, not 15. null coerces to 0, so _.mean([10, null, 20]) is (10+0+20)/3 = 10 too. Filter them out if you only want defined numbers.
_.mean handles the empty-array case explicitly (returns NaN instead of throwing on reduce-with-no-initial-value), skips undefined elements, and pairs with _.meanBy for object arrays. For pure numeric arrays you've already validated, native reduce is just as fast.
No. _.mean([0.1, 0.2, 0.3]) is 0.20000000000000004 because it's literally (0.1 + 0.2 + 0.3) / 3 in IEEE-754. Apply .toFixed(n) or Math.round-with-scaling on the result if you need a clean string.

Summary

  • Purpose: arithmetic mean of an array of numbers using baseSum / length—no statistics, no validation.
  • Remember: NaN on empty/null input; undefined elements skipped from sum but counted in length; strings trigger concatenation; BigInts throw.
  • Next: Lodash _.meanBy() when you need a per-element score function or property path, or read the official Lodash docs for _.mean.
Did you know?

_.mean([]) returns NaN, not undefinedbaseMean literally does 0 / 0 when the array is empty or nullish.

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful