String.prototype.endsWith()
The suffix half of the startsWith pair. Its optional second argument is a LENGTH to pretend the string has, not an index to start from — the opposite convention from startsWith.
Demo
Checking an extension is the canonical use, and the second case shows why it beats includes: 'report.jsonx' CONTAINS '.json' but does not end with it, so a contains-check would wrongly accept it. Uppercase filenames are a real-world hazard — extensions are conventionally case-insensitive, so lowercase before testing. And as with the other two membership methods, an empty suffix is always present.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| searchString | string | yes | The suffix to test for. A RegExp is a TypeError, as with startsWith and includes. |
| endPosition | number | no (length) | Treat the string as if it ended here — as if it had been truncated to this many characters. Not an index to search from. |
Return value
boolean — True if the string ends with the search text — or would, if it were truncated to endPosition characters.
Common patterns
const isJson = name.toLowerCase().endsWith('.json');
const base = url.endsWith('/') ? url.slice(0, -1) : url;
const isImage = ['.png', '.jpg'].some(e => name.endsWith(e));
Examples
Pitfalls
'hello'.endsWith('ell', 4)
'hello'.endsWith('ell')
'REPORT.JSON'.endsWith('.json')
'REPORT.JSON'.toLowerCase().endsWith('.json')
file.name.endsWith('.png')
file.type === 'image/png'
'abc'.endsWith(/c/)
/c$/.test('abc')
When to use
- File extension checks, after lowercasing
- Trailing slash and delimiter normalisation
- Detecting a suffix marker on a key or identifier
- Anywhere slice(-n) === x appears
- The match may be anywhere → includes
- You are testing the beginning → startsWith
- You need a pattern → an anchored RegExp with test
- Validating upload content → check the MIME type or the bytes
Notes
FAQ
Because it is defined as "pretend the string ends here", which makes endsWith(x, n) equivalent to s.slice(0, n).endsWith(x). It mirrors startsWith in purpose but not in convention, which is a genuine wart — startsWith takes an index to anchor at.
'hello'.endsWith('ell', 4); // true 'hello'.slice(0, 4).endsWith('ell'); // true — the same thing