String.prototype.substring() extracts characters from a start index up to (but not including) an end index (same API as MDN String.prototype.substring()). Learn argument swapping, how negatives become 0, how it compares to slice() and substr(), five examples, and try-it labs.
01
Kind
Instance method
02
Returns
New string
03
End index
Exclusive
04
If start > end
Args swap
05
Negatives
Treated as 0
06
Baseline
Widely available
Fundamentals
Introduction
Need characters between two indexes? substring(start, end) copies that window into a new string. The end index is exclusive — just like slice().
Two quirks to remember: if start is greater than end, the arguments are swapped; and negative numbers are treated as 0 (they do not count from the end). For end-relative indexes, prefer slice().
💡
Beginner tip
substring ≠ substr ≠ sub. substring uses two indexes. substr uses length (legacy). sub builds HTML <sub> tags.
Use substring for index windows. For search-and-replace, reach for replace() or split/join instead of hand-rolled loops.
Applications
🚀 Common Use Cases
Take a prefix / mid-section — substring(0, n) or substring(a, b).
Drop a known prefix length — substring(prefix.length).
Last n chars without negatives — substring(str.length - n).
Order-independent windows — when you want swap behavior if start > end.
Prefer slice for suffixes — slice(-n) is clearer than length math.
Not for delimiter cuts — use split() for CSV / words.
🧠 How substring() Builds the Result
1
Read start / end
Default end to the string length when omitted.
Input
2
Clamp and swap
Negatives / NaN → 0; if start > end, swap them.
Normalize
3
Copy the window
Copy from start up to (not including) end.
Extract
4
✅
Return a new string
Original str never changes.
Important
📝 Notes
The end index is exclusive.
If start > end, the arguments are swapped (unlike slice).
Negative values and NaN are treated as 0.
Do not confuse with deprecated substr() (length-based).
Prefer slice(-n) for suffixes instead of length - n math.
Always capture the return value — the original string is unchanged.
Compatibility
Browser & Runtime Support
String.prototype.substring() is Baseline Widely available — supported across modern browsers since July 2015 (and far earlier as a core language feature).
✓ Baseline · Widely available
String.substring()
Safe for production in browsers and runtimes (Node.js, Deno, Bun). Prefer slice() when you need negative indexes.
UniversalWidely available
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
substring()Excellent
Bottom line: Use String.substring() to copy between two indexes. Remember it swaps if start > end, and negatives become 0 — use slice() for end-relative cuts.
Wrap Up
Conclusion
String.prototype.substring() extracts between two indexes with an exclusive end. It is a solid, standard tool — just remember the swap rule and that negatives are not “from the end.” For end-relative work, prefer slice(); avoid legacy substr().
Hand-roll replace loops with substring when replace exists
Mutate strings — always use the return value
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about String.substring()
Extract between indexes — exclusive end, swap if reversed.
5
Core concepts
📝01
Returns
new string
API
✂️02
End
exclusive
Rule
🔁03
Start > end
swaps
Quirk
🔙04
Negatives
become 0
Index
⚡05
Mutates
no
Immutable
❓ Frequently Asked Questions
String.prototype.substring(indexStart, indexEnd?) returns a new string from indexStart up to (but not including) indexEnd. Omit indexEnd to go to the end of the string.
No. indexEnd is exclusive — the character at indexEnd is not included. For example "Mozilla".substring(1, 3) returns "oz".
substring() swaps the two arguments. So "Mozilla".substring(5, 2) is the same as "Mozilla".substring(2, 5) and returns "zil". slice() would return "" instead.
Unlike slice(), substring() treats negative values (and NaN) as 0. It does not count from the end of the string.
substring(start, end) uses two indexes. substr(start, length) uses a length (and is deprecated). Prefer substring or slice over substr.
Both are fine for non-negative indexes. Prefer slice() when you need negative indexes from the end. Prefer substring() only if you rely on its swap-when-start-greater-than-end behavior.
Did you know?
"Mozilla".substring(1, 0) and "Mozilla".substring(0, 1) both return "M" because substring swaps when start > end. The same call with slice(1, 0) returns an empty string — a classic interview gotcha.