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.

5 min read

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:

MethodSecond argument meansNegative indicesStatus
slice(start, end)End position (exclusive)Count from the endModern standard
substring(start, end)End position (exclusive)Treated as 0Legacy, but safe
substr(start, length)Number of charactersCount from the endDeprecated

With positive numbers and a start smaller than end, all three produce the same result:

javascriptjavascript
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.

javascriptjavascript
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:

javascriptjavascript
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.

javascriptjavascript
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.

javascriptjavascript
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.

javascriptjavascript
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.

javascriptjavascript
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.

javascriptjavascript
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.

javascriptjavascript
// 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 toUse
Extract from position A to Bslice(A, B)
Get the last N charactersslice(-N)
Drop the last N charactersslice(0, -N)
Maintain old substring codeKeep if it works, use slice for new lines
Replace old substr codeRewrite with slice

For all new JavaScript code, slice is the answer.

Rune AI

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.
RunePowered by Rune AI

Frequently Asked Questions

Which method should I use: slice, substring, or substr?

Use slice(). It handles negative indices intuitively, matches array slice behavior, and is the modern standard. Avoid substr(), which is deprecated and may be removed from future JavaScript versions.

Does slice work the same on strings as on arrays?

Yes. String slice and array slice follow the same rules: start index is inclusive, end index is exclusive, and negative indices count from the end.

Can I use slice with only one argument?

Yes. slice(start) extracts from the start position to the end of the string. substring(start) does the same.

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.