String.prototype.lastIndexOf()

Returns the index of the last occurrence of a substring, searching backwards from the end.

Signature
lastIndexOf(searchString)
lastIndexOf(searchString, position)
  • Added in JavaScript ECMAScript 1

Parameters

ParameterTypeDescription
$searchStringstringThe substring to search for. All values are coerced to strings, so omitting it searches for the literal text "undefined".
$positionoptionalnumber= InfinityThe match must start at or before this index. Values above str.length search the whole string; values below 0 behave like 0, so only index 0 is examined.

Return value

numberThe index of the last occurrence of searchString that starts at or before position, or -1 if it is not found.

lastIndexOf() scans backwards and reports where the final match starts. The returned index is still measured from the left, which is what makes it composable with slice().

position is a start bound, not an end bound

The optional second argument constrains where the match may begin, not where it may finish. "canal".lastIndexOf("a", 2) is 1: the match at index 3 begins after the bound, so it is excluded. A negative position collapses to 0, meaning only a match starting at index 0 can be found — "canal".lastIndexOf("c", -5) is 0 but "canal".lastIndexOf("a", 0) is -1. Because the default is Infinity rather than 0, a NaN position searches the entire string instead of clamping to the front — the opposite of indexOf().

The classic use

Splitting on the last separator: a file extension, the final path segment, a package's version suffix. Guard the not-found case first — lastIndexOf(".") returning -1 makes slice(-1 + 1) become slice(0), which silently hands back the whole string as if it were the extension.

An empty search string returns min(position, str.length), so it never reports -1.

Example

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

When to use it

  • Extract a file extension from a filename
  • Take the last path segment after the final slash
  • Trim everything after the last comma in a formatted list
  • Find the closing occurrence of a delimiter when scanning backwards

Frequently asked questions

How do I get the file extension from a filename in JavaScript?

Use name.slice(name.lastIndexOf(".") + 1), but check first that lastIndexOf(".") is greater than 0, otherwise a name with no dot returns itself.

What does the second argument of lastIndexOf() do?

It caps where the match may start, not where it may end, and defaults to Infinity. "canal".lastIndexOf("a", 2) is 1 because the match at index 3 starts past the bound.

What is the difference between indexOf() and lastIndexOf()?

indexOf() scans forwards and returns the first match; lastIndexOf() scans backwards and returns the last. Both report a left-based index and both return -1 when nothing matches.

More examples

A safe file-extension helper

The dot > 0 guard rejects both "no dot at all" (-1) and leading-dot filenames (0). The final line shows what happens without it: -1 + 1 is 0, so slice returns the whole name.

Example · javascript
function extension(name) {
  const dot = name.lastIndexOf(".");
  return dot > 0 ? name.slice(dot + 1) : "";
}

console.log(extension("report.final.pdf")); // "pdf"
console.log(JSON.stringify(extension("README"))); // ""
console.log(JSON.stringify(extension(".gitignore"))); // "" — dotfile, not an ext

// Without the guard:
console.log("README".slice("README".lastIndexOf(".") + 1)); // "README"

Last path segment and directory

One index splits the path into both halves. When there is no slash, the basename still comes out right by accident, but the directory half becomes an empty string — handle that case explicitly.

Example · javascript
const p = "/var/log/nginx/access.log";
const cut = p.lastIndexOf("/");

console.log(p.slice(cut + 1)); // "access.log"
console.log(p.slice(0, cut)); // "/var/log/nginx"

const flat = "access.log";
console.log(flat.slice(flat.lastIndexOf("/") + 1)); // "access.log"
console.log(JSON.stringify(flat.slice(0, flat.lastIndexOf("/")))); // ""

Discussion

  • Be the first to comment on this lesson.