String Slicing in JavaScript


Not only we can select a single character from a string, but we can also select a sequence of consecutive characters (e.g. substring) from a string.

To achieve this, we use the slice() method like this:

string.slice(startIndex, endIndex);

This is called slicing a string. It returns the substring from startIndex to endIndex.

Here is an example:

let language = "JavaScript";
let substring = language.slice(2, 6);

console.log(substring); // Output: "vaSc"
console.log(language); // Output: "JavaScript"

The startIndex is a zero-based index at which we start extraction and the endIndex is also zero-based index before which we end the extraction.

The substring will not include the character at endIndex. You can see in our example that language[2] (v) was included while language[6] (r) was excluded.

Also notice that language preserved its value. The slicing does not affect the original string. It just creates a brand new one representing the sliced substring.


If you omit the endIndex, the slice() extracts to the end of the string:

let language = "JavaScript";
let substring = language.slice(4);

console.log(substring); // Output: "Script"

Assignment
Follow the Coding Tutorial and let's slice some strings!


Hint
Look at the examples above if you get stuck.


JavaScript String Slicing: slice(), substring(), and substr() — Which to Use

JavaScript has three methods that extract substrings — and developers mix them up constantly. Getting them straight pays off immediately: you'll write cleaner code, avoid silent bugs with negative indices, and know exactly why slice() is the one to reach for first. Slicing appears constantly in real code: parsing URLs, trimming display text, extracting file extensions, and working with timestamps.

Visualising the Indices

Like all strings, JavaScript uses zero-based indexing. Think of the index as the position before each character — slice(2, 6) cuts at position 2 and position 6:

const s = "JavaScript";
//          J  a  v  a  S  c  r  i  p  t
//          0  1  2  3  4  5  6  7  8  9   ← positive
//        -10 -9 -8 -7 -6 -5 -4 -3 -2 -1   ← negative (slice only)

console.log(s.slice(2, 6));    // "vaSc"   — positions 2, 3, 4, 5
console.log(s.slice(4));       // "Script" — from 4 to end
console.log(s.slice(0, 4));    // "Java"   — first 4 characters

The Three Methods: slice vs substring vs substr

All three extract substrings, but they handle parameters very differently:

const s = "JavaScript";

// slice(start, end) — end exclusive, supports negative indices ✓
console.log(s.slice(0, 4));      // "Java"
console.log(s.slice(-6, -2));    // "Scri"  — negative indices work

// substring(start, end) — end exclusive, NO negative indices
// Negatives treated as 0; swaps args if start > end
console.log(s.substring(0, 4));  // "Java"
console.log(s.substring(-4));    // "JavaScript" — -4 becomes 0 (no negative support)

// substr(start, length) — second arg is LENGTH not end index (deprecated)
console.log(s.substr(4, 6));     // "Script" — 6 chars starting at index 4

Rule of thumb: Use slice() — it's the most predictable and supports negative indices. Avoid substr() (deprecated in modern JS).

Negative Indices in slice()

Negative indices count backward from the end of the string. -1 is the last character, -2 is second-to-last:

const s = "JavaScript";

console.log(s.slice(-1));      // "t"      — last character
console.log(s.slice(-6));      // "Script" — last 6 characters
console.log(s.slice(-6, -2));  // "Scri"   — last 6 to last 2 (exclusive)

// ES2022 shorthand for last character:
console.log(s.at(-1));         // "t"
console.log(s.at(-2));         // "p"

Out-of-Bounds: No Error, Just Clipped

Unlike Java, JavaScript's slice() never throws — it silently clips out-of-range indices:

const s = "Hi";

console.log(s.slice(0, 100));   // "Hi"   — clips to string length
console.log(s.slice(5, 10));    // ""     — empty string (start past end)
console.log(s.slice(-100));     // "Hi"   — clips to start of string

Dynamic Slicing with indexOf()

Combine indexOf() with slice() to find boundaries at runtime — one of the most common patterns in string processing:

// Extract domain from an email address:
const email = "user@example.com";
const atPos = email.indexOf("@");
const domain = email.slice(atPos + 1);
console.log(domain);          // "example.com"

// Extract path from a URL (skip "https://"):
const url = "https://example.com/blog/post-1";
const pathStart = url.indexOf("/", 8);
const path = url.slice(pathStart);
console.log(path);            // "/blog/post-1"

// Truncate a title for a preview card:
const title = "Introduction to Machine Learning";
const preview = title.length > 20 ? title.slice(0, 20) + "..." : title;
console.log(preview);         // "Introduction to Mach..."

Real-World Patterns

// Get file extension:
const filename = "report_2024.pdf";
const ext = filename.slice(filename.lastIndexOf(".") + 1);
console.log(ext);             // "pdf"

// Remove first and last characters (trim brackets, quotes):
const withBrackets = "[hello]";
const inner = withBrackets.slice(1, -1);
console.log(inner);           // "hello"

// Check if string starts with a prefix (manual version):
const route = "/api/users";
console.log(route.slice(0, 4) === "/api");   // true
// (Or use the built-in: route.startsWith("/api"))

Key Takeaways

What to Learn Next

With slice() solid, explore the JavaScript string methods that pair with it: indexOf() and lastIndexOf() to locate positions, startsWith() and endsWith() for prefix/suffix checks (often cleaner than slicing), and split() to break a string into an array by delimiter. In algorithm problems, slicing is key for palindrome checking, anagram detection, and sliding window patterns.