String.prototype.at()

Returns the character at an index, counting back from the end when the index is negative.

Signature
at(index)
  • Added in JavaScript ECMAScript 2022

Parameters

ParameterTypeDescription
$indexnumberThe index (position) of the character to return. A negative index counts back from the end of the string.

Return value

string | undefinedA string containing the single UTF-16 code unit at the given position, or undefined when the index is out of range.

at() is the modern index accessor. Its whole reason to exist is the negative index: str.at(-1) is the last character, where bracket notation forces you to write str[str.length - 1] and repeat the expression that produced the string.

How it differs from the alternatives

Out of rangeResult
"abc".at(5)undefined
"abc"[5]undefined
"abc".charAt(5)""

That difference matters in conditionals. charAt() hands back an empty string, which is falsy but still a string; at() hands back undefined, so ?. and ?? behave the way you expect and a typo'd index shows up as undefined rather than silently becoming "".

Index handling

The index is converted to an integer, so a fractional index truncates and undefined becomes 0. Negative indexes resolve as index + str.length; if that is still negative, the result is undefined.

Like every other index-based string method, it works in UTF-16 code units, so at(-1) on a string ending in an emoji gives you the lone trailing surrogate — half a character.

Example

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

When to use it

  • Grab the last character to check for a trailing slash or punctuation
  • Read the second-to-last character without recomputing the length
  • Pull an initial from a name inside a map callback
  • Test the sign character at the front of a formatted number

Frequently asked questions

How do I get the last character of a string in JavaScript?

Use str.at(-1). It counts back from the end, so you never have to write str[str.length - 1], and it returns undefined for an empty string.

What is the difference between at() and charAt()?

at() accepts negative indexes and returns undefined when out of range; charAt() rejects negative indexes as out of range and returns an empty string instead of undefined.

Does String.prototype.at() work in older browsers?

It has been available across browsers since March 2022 (ECMAScript 2022). For older engines, use str[str.length - 1] or a polyfill.

More examples

at() vs charAt() vs bracket access out of range

Both report "(none)" here, but the typeof line shows the real difference: charAt() always returns a string, so a bad index is indistinguishable from a genuinely empty result.

Example · javascript
const s = "abc";
console.log(s.at(5), s[5], JSON.stringify(s.charAt(5)));
// undefined undefined ""

// undefined lets optional chaining and ?? work
console.log(s.at(5)?.toUpperCase() ?? "(none)"); // "(none)"
// charAt gives an empty string, which is still a string
console.log(s.charAt(5).toUpperCase() || "(none)"); // "(none)"
console.log(typeof s.charAt(5), typeof s.at(5)); // string undefined

Surrogate pairs break negative indexing

at(-1) returns the trailing half of the emoji's surrogate pair. Spreading into an array first splits by code point, so Array.prototype.at() returns the whole emoji.

Example · javascript
const msg = "Nice \u{1F44D}";
console.log(msg.at(-1).codePointAt(0).toString(16)); // dc4d — lone surrogate
console.log(msg.at(-1) === "\u{1F44D}"); // false

const chars = [...msg];
console.log(chars.at(-1) === "\u{1F44D}"); // true
console.log(chars.at(-1).codePointAt(0).toString(16)); // 1f44d

Discussion

  • Be the first to comment on this lesson.