jsguides

String.prototype.at()

at(index)

The at() method returns the character at the specified index in a string. Its standout feature is support for negative indices, which count backward from the end—this makes it the preferred method when you need to access characters relative to a string’s end.

Syntax

string.at(index)
  • index: An integer representing the position of the character. Positive indices count from the start (0-indexed), negative indices count from the end.
  • Returns: A string containing the character at the specified index, or undefined if the index is out of bounds.

TypeScript Signature

interface String {
  at(index: number): string | undefined;
}

The TypeScript signature confirms that at() accepts any integer and returns either a single-character string or undefined — no empty strings, no coercion to zero. This is the same contract as Array.prototype.at(), making at() consistent across strings and arrays in a way that charAt() never was.

Basic character retrieval

const text = "Hello";

console.log(text.at(0)); // "H"
console.log(text.at(1)); // "e"
console.log(text.at(4)); // "o"

Forward indexing with at() works the same as bracket notation or charAt() — zero-based, first character at index 0, last at length - 1. The real advantage appears when you need to count from the end of the string, where bracket notation silently returns undefined and charAt() misinterprets the index.

Negative indices (index-from-end)

This is where at() shines. Use negative indices to access characters counting backward from the end:

const filename = "document.pdf";

console.log(filename.at(-1)); // "f" (last character)
console.log(filename.at(-2)); // "f"
console.log(filename.at(-3)); // "."
console.log(filename.at(-4)); // "d"

Negative indices work the same way as slice()-1 is the last character, -2 is second-to-last, and so on. This is especially useful for file extensions, URL path segments, and any string where you need the tail without knowing the total length ahead of time. Compared to the alternatives, at() is the only method that handles negative indexing directly without manual length calculations.

at() vs charAt() vs bracket notation

Here’s how at() compares to the alternatives:

const text = "Hi";

// at(): supports negative indices, returns undefined for out-of-bounds
console.log(text.at(0));    // "H"
console.log(text.at(-1));   // "i" (negative works!)
console.log(text.at(5));    // undefined

// charAt(): no negative index support, returns empty string for out-of-bounds
console.log(text.charAt(0));  // "H"
console.log(text.charAt(-1)); // "" (negative becomes 0)
console.log(text.charAt(5));  // "" (empty string)

// bracket notation: no negative index support, returns undefined
console.log(text[0]);       // "H"
console.log(text[-1]);      // undefined (no negative support)
console.log(text[5]);       // undefined

The key differences:

  • at(): Supports negative indices, returns undefined for out-of-bounds
  • charAt(): No negative indices, returns empty string "" for out-of-bounds
  • Bracket notation: No negative indices, returns undefined for out-of-bounds

Out of bounds behavior

When the index exceeds the string’s length or is otherwise invalid, at() returns undefined rather than an empty string:

const text = "test";

console.log(text.at(10));     // undefined
console.log(text.at(-10));    // undefined (too far from end)
console.log(text.at());       // undefined (index becomes NaN → 0)

This undefined return is useful—it clearly signals “no character found” rather than returning an empty string that might go unnoticed.

Why at() Is Useful

The main reason to use String.prototype.at() is that it reads the same way as the array version. If you already know at() from arrays, the string version gives you the same negative-index behavior for text. That makes it handy for filenames, suffix checks, and quick lookups at the tail of a string.

It is also a little easier to read than manual index math. When you see text.at(-1), the intent is obvious: grab the last character. That is clearer than calculating text.length - 1, especially when the code is part of a longer expression.

Choosing Between at() and charAt()

at() and charAt() overlap, but charAt() returns an empty string when the index is out of bounds, while at() returns undefined. That difference matters when the result is part of a conditional or a string concatenation. at() tends to be the better choice when you want the absence of a character to stand out more clearly.

If you are supporting older environments, charAt() remains the fallback. But when ES2022 is available, at() gives you the more expressive API, especially for negative indexing.

Browser Compatibility

BrowserVersion
Chrome92+
Firefox90+
Safari16.4+
Edge92+
Node.js16.6.0+

Added in ES2022. Not supported in older browsers—use a polyfill or fall back to charAt() when needed.

See Also