JavaScript String Slice Substring and Substr Guide
Compare JavaScript slice, substring, and substr for extracting parts of a string. Learn the key differences, which one to use, and why substr is deprecated.
JavaScript provides three methods for extracting a portion of a string: slice, substring, and substr. They look similar at first glance, but they differ in how they handle negative numbers and what the second argument means.
Here is the core difference in one table:
| Method | Second argument means | Negative indices | Status |
|---|---|---|---|
| slice(start, end) | End position (exclusive) | Count from the end | Modern standard |
| substring(start, end) | End position (exclusive) | Treated as 0 | Legacy, but safe |
| substr(start, length) | Number of characters | Count from the end | Deprecated |
With positive numbers and a start smaller than end, all three produce the same result:
const word = "JavaScript";
console.log(word.slice(0, 4));
console.log(word.substring(0, 4));
console.log(word.substr(0, 4));All three print Java. The differences only appear when you use negative values, swap the argument order, or misunderstand what the second argument represents.
For an overview of where extraction fits among all string operations, see the JavaScript string methods guide. For checking substrings instead of extracting them, see the guide to includes, startsWith, and endsWith.
slice(): the one you should use
The slice method extracts characters from start up to but not including end. If you omit end, it extracts everything from start to the end of the string.
const word = "JavaScript";
console.log(word.slice(0, 4));
console.log(word.slice(4));The first call prints Java by extracting positions 0 through 3. The second prints Script by going from position 4 to the end. The end index is exclusive, which is consistent with how slice works on arrays.
Negative indices count backward from the end of the string:
const word = "JavaScript";
console.log(word.slice(-6));
console.log(word.slice(0, -6));
console.log(word.slice(-6, -1));The first prints Script because -6 means "six characters from the end." The second prints Java because it means "everything except the last six characters."
The third prints Scrip by going from 6-from-end up to but not including the last character. This negative-index behavior is the main reason to choose slice over the alternatives.
substring(): similar but quirkier
The substring method also extracts from start to end, but with two behaviors that differ from slice. If start is greater than end, substring silently swaps them. If either argument is negative, substring converts it to zero.
const word = "JavaScript";
console.log(word.substring(0, 4));
console.log(word.substring(4, 0));Both print Java. The second call swaps its arguments behind the scenes, becoming substring(0, 4). This automatic swapping is unique to substring.
console.log(word.substring(-6));
console.log(word.substring(-6, 4));
console.log(word.slice(-6));The first prints the entire string JavaScript because -6 becomes 0. The second prints Java for the same reason. Compare the third: slice(-6) correctly counts from the end and prints Script. The zero-conversion behavior makes substring harder to reason about than slice.
substr(): deprecated, avoid it
The substr method is unique because its second argument is a length, not an end position. It is also deprecated and not part of the core ECMAScript specification anymore.
const word = "JavaScript";
console.log(word.substr(4, 3));
console.log(word.substr(0, 4));The first prints Scr because it means "starting at position 4, take 3 characters." The second prints Java because it means "starting at 0, take 4 characters." Every other extraction method uses an end position for the second argument.
Browsers keep substr for backward compatibility, but it may be removed in the future. Do not use it in new code. If you encounter it in an older codebase, mentally translate it: str.substr(4, 3) is equivalent to str.slice(4, 4 + 3).
Negative index behavior compared
This is where the three methods diverge the most. With a single negative argument, slice and substr count from the end, but substring converts the negative to zero.
const word = "JavaScript";
console.log(word.slice(-6));
console.log(word.substring(-6));
console.log(word.substr(-6));slice(-6) prints Script because it counts from the end. substring(-6) prints the entire JavaScript because -6 becomes 0. substr(-6) also prints Script because it counts from the end.
With two arguments, the differences grow wider. substr's second argument is a length, so word.substr(-6, 3) takes 3 characters starting from 6-from-end, producing Scr. slice and substring use an end position instead, which changes the result completely.
Practical patterns with slice
Since slice is the method you should use, here are the five patterns for common extraction needs. The first two patterns cover getting a prefix or suffix from a string.
const str = "JavaScript";
// First N characters: start at 0, end at N
console.log(str.slice(0, 4)); // "Java"
// Last N characters: negative start counts from the end
console.log(str.slice(-6)); // "Script"The slice(0, 4) call extracts positions 0, 1, 2, and 3. The end index is always exclusive, which matches how array slice behaves.
The remaining three patterns handle removing characters from either end or extracting a middle portion.
// Everything except first N: provide only start, omit end
console.log(str.slice(4)); // "Script"
// Everything except last N: negative end drops from the right
console.log(str.slice(0, -6)); // "Java"
// Middle section: both arguments positive
console.log(str.slice(2, 8)); // "vaScri"When you omit the end argument, slice extracts from start to the end of the string. A negative end argument means "stop this many characters before the end," which is useful for trimming suffixes. Passing two positive arguments, as in slice(2, 8) above, extracts a middle section between those positions.
These five shapes cover almost every real-world extraction scenario. Memorize the pattern and you will rarely need substring or substr.
When you might still see the other methods
substring appears in older codebases and tutorials written before slice became the convention. It works correctly as long as you use positive indices and keep start smaller than end.
substr appears in very old code. In your own code, always write the slice version. There is no situation where substring or substr does something slice cannot do more clearly.
Common mistakes
Using substr in new code is the most avoidable mistake. Even though str.substr(-4) works today, it relies on a deprecated method. Use str.slice(-4) instead.
Expecting substring to handle negative indices is another common error. The expression word.substring(-2) returns the entire string, not the last two characters. Use word.slice(-2) for that.
Confusing substr's second argument as an end position leads to subtle bugs. word.substr(4, 6) means "take 6 characters starting at position 4," producing "Script".
If you meant "from position 4 to position 6," you want word.slice(4, 6), which returns only "Sc".
Quick decision guide
| You want to | Use |
|---|---|
| Extract from position A to B | slice(A, B) |
| Get the last N characters | slice(-N) |
| Drop the last N characters | slice(0, -N) |
| Maintain old substring code | Keep if it works, use slice for new lines |
| Replace old substr code | Rewrite with slice |
For all new JavaScript code, slice is the answer.
Rune AI
Key Insights
- slice(start, end) is the recommended method. Negative indices count from the end.
- substring(start, end) treats negative values as 0 and swaps arguments if start > end.
- substr(start, length) is deprecated. Its second argument is a length, not an end position.
- Prefer slice in all new code. It behaves consistently across strings and arrays.
- All three methods return a new string. The original string is never modified.
Frequently Asked Questions
Which method should I use: slice, substring, or substr?
Does slice work the same on strings as on arrays?
Can I use slice with only one argument?
Conclusion
slice, substring, and substr all extract parts of a string, but they differ in negative-index handling and what the second argument means. Use slice as your default: negative indices count from the end, the behavior matches array slice, and it is the modern standard. Avoid substr entirely because it is deprecated.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.