String.prototype.substring()

Extracts the characters between two indices and returns them as a new string.

Signature
substring(indexStart)
substring(indexStart, indexEnd)
  • Added in JavaScript ES1

Parameters

ParameterTypeDescription
$indexStartnumberThe index of the first character to include in the returned substring.
$indexEndoptionalnumberThe index of the first character to exclude from the returned substring. If omitted or undefined, extraction runs to the end of the string.

Return value

stringA new string containing the specified part of the given string.

substring() copies the characters from indexStart up to but not including indexEnd. The original string is untouched — strings are immutable, so you always get a new one back.

How it sanitises its arguments

This is the method's defining trait, and the reason people either love it or avoid it. It never lets an index escape the string:

  • Any argument below 0 becomes 0; anything above str.length becomes str.length.
  • NaN is treated as 0.
  • If indexStart is greater than indexEnd, the two arguments are swapped, so s.substring(4, 0) and s.substring(0, 4) return the same thing.

substring vs slice

Both take start and end indices, but slice() accepts negative indices as offsets from the end and returns an empty string when start > end. Reach for substring() when the indices come from a source you do not fully trust — the results of indexOf(), a user-supplied offset, arithmetic that might go negative — and you want clamping rather than a surprise. Reach for slice() when you actually want -3 to mean "three from the end".

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Pull a fixed-width field out of a flat text record
  • Truncate a label to a maximum length before display
  • Split a key at a delimiter found with indexOf()
  • Read the year out of an ISO date string

Frequently asked questions

What is the difference between substring and slice in JavaScript?

slice() accepts negative indices as offsets from the end of the string and returns an empty string when start is greater than end, while substring() clamps negative values to 0 and swaps the arguments when start is greater than end. Use slice() when you want to count backwards; use substring() when you want out-of-range indices quietly corrected.

Why does substring return characters when start is bigger than end?

Because substring() swaps its two arguments whenever indexStart exceeds indexEnd, by specification. s.substring(4, 0) is evaluated as s.substring(0, 4). If you need a reversed range to yield an empty string, use slice() instead.

Does substring modify the original string?

No. JavaScript strings are immutable, so substring() always returns a brand-new string and leaves the original variable pointing at the untouched value. Even substring(0) returns a copy rather than the same reference in spirit.

More examples

Cutting a key at a delimiter

The output shows the header split into name and value. The last line demonstrates the clamping: a missing delimiter makes indexOf return -1, and substring turns that into 0 rather than throwing or counting from the end.

Example · javascript
const entry = "content-type: application/json";
const colon = entry.indexOf(":");

const name = entry.substring(0, colon);
const value = entry.substring(colon + 1).trim();

console.log(name);  // "content-type"
console.log(value); // "application/json"

// When there is no delimiter, indexOf returns -1,
// which substring clamps to 0.
console.log(JSON.stringify("novalue".substring(0, -1))); // ""

substring vs slice on negative indices

The two methods disagree on every line. slice() honours negative indices and returns an empty string for a reversed range; substring() clamps and swaps. Picking the wrong one is the most common source of off-by-everything string bugs.

Example · javascript
const s = "abcdef";

console.log(s.substring(-2));   // "abcdef" — -2 clamped to 0
console.log(s.slice(-2));       // "ef"     — counts from the end

console.log(s.substring(4, 1)); // "bcd"    — arguments swapped
console.log(s.slice(4, 1));     // ""       — empty when start > end

console.log(s.substring(NaN, 3)); // "abc" — NaN treated as 0

Truncating with an ellipsis

Short input is returned unchanged; the long headline is cut to 19 characters plus an ellipsis, 20 in total. Because substring clamps, the function is safe even if max is larger than the string.

Example · javascript
function truncate(text, max) {
  return text.length <= max ? text : text.substring(0, max - 1) + "…";
}

console.log(truncate("Short", 20));
console.log(truncate("A rather long headline about strings", 20));
console.log(truncate("", 20).length);

Discussion

  • Be the first to comment on this lesson.