How to find the minimum value in an array in JavaScript
Finding the minimum value in numeric arrays is crucial for data validation, setting lower bounds, calculating ranges, and implementing features like price filters or threshold alerts in JavaScript applications.
With over 25 years of experience in software development and as the creator of CoreUI, I have implemented minimum value calculations in components like slider controls, budget trackers, and validation systems where identifying the lowest values ensures proper data boundaries.
From my extensive expertise, the most elegant and efficient solution is using Math.min() combined with the spread operator to find the smallest number.
This approach is concise, performant, and utilizes JavaScript’s built-in mathematical functions for reliable results.
Use Math.min() with the spread operator to find the smallest value in an array.
const numbers = [3, 7, 2, 9, 1, 5]
const minimum = Math.min(...numbers)
// Result: 1
The Math.min() function finds the smallest of the provided arguments, and the spread operator ... expands the array elements as individual arguments to the function. In this example, Math.min(...numbers) is equivalent to Math.min(3, 7, 2, 9, 1, 5), which returns 1 as the smallest value. This method only works with numeric arrays and will return NaN if any element cannot be converted to a number. For empty arrays, it returns Infinity.
Using Math.min() with the Spread Operator
The spread operator approach is the most common way to find the minimum value in modern JavaScript. It handles negative numbers and zero correctly.
const prices = [29.99, 49.99, 19.99, 99.99, 9.99]
const lowestPrice = Math.min(...prices)
console.log(lowestPrice) // 9.99
const temperatures = [-5, 12, 0, 8, -3, 15]
const coldest = Math.min(...temperatures)
console.log(coldest) // -5
// Works correctly with zero
const withZero = [5, 0, 3, 8, 1]
const min = Math.min(...withZero)
console.log(min) // 0
Note that Math.min() handles negative numbers and zero correctly. The function compares all values numerically regardless of sign. Be aware that for empty arrays, Math.min() returns Infinity, so always validate your input before calling this method.
Using reduce() for Large Arrays
For arrays larger than ~100,000 elements, the spread operator can cause a stack overflow because it passes every element as a separate function argument. The reduce() method processes elements one at a time and handles any array size safely.
const largeArray = Array.from({ length: 200_000 }, () =>
Math.floor(Math.random() * 1_000_000)
)
const minimum = largeArray.reduce(
(min, current) => (current < min ? current : min),
Infinity
)
console.log(minimum)
The reduce() approach iterates through each element and keeps track of the smallest value found so far. The initial value is set to Infinity so that any real number in the array will be smaller. This pattern is also useful when you need to find the minimum and track additional information in the same pass, such as the index of the smallest element.
const scores = [85, 92, 78, 95, 88]
const result = scores.reduce(
(acc, current, index) => {
if (current < acc.value) {
return { value: current, index }
}
return acc
},
{ value: Infinity, index: -1 }
)
console.log(result) // { value: 78, index: 2 }
Finding the Minimum in an Array of Objects
Real-world data is often stored as arrays of objects. Use Math.min() with map() to extract the numeric property before comparing.
const products = [
{ name: 'Shirt', price: 29.99 },
{ name: 'Jacket', price: 89.99 },
{ name: 'Hat', price: 14.99 },
{ name: 'Shoes', price: 119.99 }
]
// Extract the minimum price
const minPrice = Math.min(...products.map((p) => p.price))
console.log(minPrice) // 14.99
// Get the entire object with the lowest price
const cheapest = products.reduce((min, product) =>
product.price < min.price ? product : min
)
console.log(cheapest) // { name: 'Hat', price: 14.99 }
When you need the full object (not just the numeric value), reduce() is the better choice. It avoids a second lookup step and keeps the code efficient. This pattern is commonly used when building price filters or highlighting the lowest-value item in tables built with the CoreUI Smart Table component.
Handling Mixed or Invalid Data
Arrays from external APIs or user input may contain non-numeric values. Never use .filter(Number) to clean them — it removes 0 because zero is falsy. Instead, filter explicitly with typeof and Number.isFinite().
const mixed = [10, 'hello', null, 42, undefined, 0, 7, NaN]
// Correct: keeps zeros, removes non-numbers
const safeMin = Math.min(
...mixed.filter((v) => typeof v === 'number' && Number.isFinite(v))
)
console.log(safeMin) // 0
// Wrong: .filter(Number) removes 0
const broken = Math.min(...mixed.filter(Number))
console.log(broken) // 7 (wrong! should be 0)
const withZeroMin = [0, 5, 3, 1]
console.log(Math.min(...withZeroMin.filter(Number))) // 1 (wrong! should be 0)
console.log(
Math.min(
...withZeroMin.filter((v) => typeof v === 'number' && Number.isFinite(v))
)
) // 0 (correct)
Always validate data at the boundary where it enters your application. This is especially important when working with chart scales in components like the CoreUI Chart where an incorrect lower bound can distort the entire visualization.
Finding the Range (Min and Max Together)
In many scenarios you need both the minimum and maximum to compute a range. Finding them in a single pass with reduce() is more efficient than calling Math.min() and Math.max() separately. For the counterpart to this article, see how to find the maximum value in an array in JavaScript.
const data = [23, 8, 45, 12, 67, 3, 34]
const range = data.reduce(
(acc, val) => ({
min: val < acc.min ? val : acc.min,
max: val > acc.max ? val : acc.max
}),
{ min: Infinity, max: -Infinity }
)
console.log(range) // { min: 3, max: 67 }
console.log(range.max - range.min) // 64
This single-pass approach is ideal for setting up axis bounds in charts or defining slider ranges in form controls.
Using a Simple for Loop
A traditional for loop is the most performant approach and works in every JavaScript environment without any limitations.
function findMin(arr) {
if (arr.length === 0) return undefined
let min = arr[0]
for (let i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i]
}
}
return min
}
const numbers = [3, 7, 2, 9, 1, 5]
console.log(findMin(numbers)) // 1
console.log(findMin([])) // undefined
This approach avoids the stack overflow risk of the spread operator and is slightly faster than reduce() because it has no function call overhead per element. Use it when performance is critical or when working with very large datasets. For related array operations, see how to find the average of an array of numbers in JavaScript.
Best Practice Note:
For most use cases, Math.min(...array) is the best choice — it is concise, readable, and fast enough for arrays under 100k elements. Switch to reduce() or a for loop only when dealing with very large datasets. Always guard against empty arrays and non-numeric values at the boundary where data enters your application rather than inside utility functions.



