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 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.
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
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 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"
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
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..."
// 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"))
slice(start, end): start inclusive, end exclusive, supports negative indices.substring() doesn't support negative indices; substr() uses length as second param and is deprecated.s.slice(-3) returns the last 3 characters.indexOf() or lastIndexOf() for dynamic boundaries.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.
AI writes the code. Problem-solving gets you hired. Build the skills you need to land your dream tech job.
Start Coding for FREE