By the end of this tutorial, you’ll use Lodash’s _.range() to build number arrays for loops, indexes, and pagination—without writing manual increment logic.
01
Core Syntax
_.range(start, end, step)
02
One arg
_.range(5) → 0..4
03
Exclusive end
End not included.
04
Custom step
Skip by 2, 5, etc.
05
Count down
Negative step.
06
vs rangeRight
Reverse order.
Fundamentals
What Is _.range()?
_.range() creates an array of numbers in order—like Python’s range. You control where the sequence starts, where it stops (exclusive), and how much it steps each time. It is one of the most practical Lodash helpers for replacing for (let i = 0; i < n; i++) when you need the index array itself.
💡
Beginner tip — one argument means “0 up to n”
_.range(5) is [0, 1, 2, 3, 4]. The lone number is the end, not the start. Start defaults to 0.
Use range for iteration helpers, zero-based indexes, page-number lists, chart tick marks, and any time you need a predictable numeric sequence in one expression.
Foundation
📝 Syntax
All arguments are optional except that you need at least one value for a non-empty result:
javascript
_.range([start = 0], end, [step = 1 or -1])
Syntax Rules
One argument — treated as end; start is 0. _.range(4) → [0, 1, 2, 3].
Two arguments — start and end (exclusive). Step defaults to 1 if start < end, else -1.
Three arguments — explicit step (can be negative for countdowns).
End is exclusive — the stop value never appears in the output array.
Empty result — _.range(0) returns []; invalid step/end combos may also yield [].
javascript
import range from "lodash/range";
range(1, 6, 2);
// [1, 3, 5]
Cheat Sheet
⚡ Quick Reference
Task
Code pattern
Result
Zero to n − 1
_.range(n)
[0..n−1]
Start to end
_.range(1, 5)
[1, 2, 3, 4]
Step by 2
_.range(0, 10, 2)
[0, 2, 4, 6, 8]
Countdown
_.range(5, 0, -1)
[5, 4, 3, 2, 1]
Loop indexes
_.range(items.length)
0..len−1
Descending order
_.rangeRight(...)
Reversed
Returns
Array
Numbers
End
Exclusive
Not included
Default step
±1
By direction
Category
Util
Sequence
Reference
🧰 Parameters
Arguments to _.range() and how they shape the output:
startOptional
First value in the sequence. Defaults to 0 when only one argument is passed (that arg becomes end).
_.range(2, 5) // start 2
endRequired*
Stop boundary—exclusive. With one arg, it is the only number you pass: _.range(end).
_.range(1, 5) // stops before 5
stepOptional
Increment (or decrement when negative). Defaults to 1 or -1 based on start vs end.
_.range(0, 20, 5)
returnArray
Dense array of numbers following the progression until the next step would reach or pass end.
[0, 1, 2, 3, 4]
Official edge case: _.range(1, 4, 0) repeats 1 (step zero)—rare in practice; prefer positive or negative steps.
Hands-On
Examples Gallery
Practical _.range() patterns with copy-ready code, sample output, and interactive Try It Yourself labs.
📚 Getting Started
Start, end, and step—the core progression pattern.
Example 1 — Custom start, end, and step
From 1 up to (but not including) 6, stepping by 2.
End is still exclusive: _.range(5, 1, -1) stops before 1, so 1 is omitted. Include zero by using end 0 with step -1 carefully, or use _.range(5, 0, -1).
Pages are 1-based, so start at 1 and use end totalPages + 1 because end is exclusive.
🚀 Beyond the Basics
range vs native alternatives and rangeRight.
Example 6 — range vs Array.from vs rangeRight
Same length indexes—different APIs. Descending values vs descending array order.
javascript
// Lodash range — explicit start/end/step
console.log(_.range(2, 5));
// [2, 3, 4]
// Native — length-based indexes
console.log(Array.from({ length: 3 }, (_, i) => i + 2));
// [2, 3, 4]
// Same numbers, reversed array order (see rangeRight tutorial)
console.log(_.rangeRight(2, 5));
// [4, 3, 2]
📤 Console output:
[2, 3, 4]
[2, 3, 4]
[4, 3, 2]
When to use which
Need countdown values? Use negative step with range. Need the array stored high-to-low? Use rangeRight.
Compare
📋 _.range vs related patterns
Topic
_.range()
_.rangeRight()
Array.from()
for loop
Returns
Number array
Number array (reversed)
Any mapped values
Side effects only
End boundary
Exclusive
Exclusive
Length-based
Custom condition
Step control
Built-in
Built-in
Via map index
Manual i++
Best for
Indexes, pages, ticks
Descending order
Custom transform
Imperative loops
Example
_.range(1, 5)
_.rangeRight(1, 5)
Array.from({length:4}, (_,i)=>i+1)
for (let i=1; i<5; i++)
🧠 How _.range() Works
1
Normalize args
One arg → start 0, that arg is end. Infer step sign from start vs end if omitted.
Setup
2
Walk the progression
Push current value, add step, repeat until the next value would cross end.
Build
3
Respect exclusive end
The end boundary itself is never pushed—same rule as Python range.
Stop rule
=
🛠
Number array
A dense list ready for map, for…of, pagination UI, or index lookups.
Important
📝 Notes
_.range(n) is 0 through n - 1, not 1 through n.
End is always exclusive—add 1 when you need an inclusive upper bound (e.g. pagination).
Count down with a negative step; do not assume two-arg reverse works without checking default step rules.
Very large ranges allocate a full array—avoid _.range(1_000_000) unless you truly need every index in memory.
For reversed output order with the same numeric progression, see _.rangeRight().
Next in the series: _.rangeRight()—same numbers, opposite array order.
Wrap Up
Conclusion
_.range() is the quick way to materialize numeric sequences in JavaScript. Once you internalize “one arg = end, exclusive stop,” it becomes a go-to for indexes, pagers, and loop helpers.
Pair it with collection methods (_.map(_.range(n), …)) or use native for…of—choose the style that reads best in your project.
Add 1 to end for inclusive upper bounds (page numbers starting at 1)
Pass explicit negative step for countdown sequences
Combine with _.map to build derived arrays from indexes
Prefer small, readable ranges over million-element allocations
❌ Don’t
Assume _.range(5) includes 5—it stops at 4
Use broken self-referential spreads (e.g. fibonacci via range map on itself)
Confuse range with rangeRight when you only need descending values—negative step may suffice
Build huge ranges when you only need lazy iteration
Pass step 0 unless you intentionally want repeated values
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about _.range()
Use these points whenever you need a numeric sequence array.
5
Core concepts
🔢01
Exclusive end
Stop before end.
Rule
🔄02
_.range(n)
0 .. n−1.
Shorthand
✅03
Step
Custom stride.
Control
📝04
Negative step
Count down.
Pattern
🛠05
rangeRight
Reverse order.
Compare
❓ Frequently Asked Questions
_.range(start, end, step) returns an array of numbers forming an arithmetic progression. It is like Python's range—handy for loops, indexes, and pagination without manual for loops.
The single value is the end (exclusive) and start defaults to 0. _.range(5) yields [0, 1, 2, 3, 4]. _.range(0) yields an empty array.
Exclusive—the end number is never included. _.range(1, 5) is [1, 2, 3, 4], not including 5.
Use a negative step when start is greater than end: _.range(5, 0, -1) gives [5, 4, 3, 2, 1]. With two args where start > end, step defaults to -1.
Both build the same numbers; rangeRight returns them in reverse order (end toward start). Use range for ascending sequences; rangeRight when you need descending array order.
Use _.range when you want explicit start/end/step math. Array.from({ length: n }, (_, i) => i) is fine for simple 0..n-1 indexes. Pick whichever reads clearer in your codebase.
Did you know?
Lodash’s _.range(-4) yields [0, -1, -2, -3] because the single argument becomes an exclusive end below zero with default step -1—not a length of four positive numbers.