String.prototype.at() reads one UTF-16 code unit at a given index (same API as MDN String.prototype.at()). Positive indexes count from the start; negative indexes count from the end — so str.at(-1) is the last character. This tutorial covers comparisons with charAt, out-of-range undefined, five examples, and try-it labs.
01
Kind
Instance method
02
Returns
1 char or undefined
03
Negative?
Yes
04
vs charAt
Cleaner end access
05
Mutates?
No
06
Baseline
Widely available
Fundamentals
Introduction
For years, beginners wrote str.charAt(str.length - 1) or str.slice(-1) to grab the last character. at() makes that obvious: str.at(-1).
Indexes are zero-based from the left. A negative index means “count back from the end,” where -1 is the last character, -2 the second-to-last, and so on.
💡
Beginner tip
Out of range, at() returns undefined — not an empty string. That makes missing indexes easier to detect than with charAt().
Examples follow MDN String.at() patterns. Use View Output or Try It Yourself for each case.
📚 Getting Started
Positive and negative indexes on a familiar sentence.
Example 1 — Positive Index
MDN demo: read a character counting from the start.
JavaScript
const sentence = "The quick brown fox jumps over the lazy dog.";
const index = 5;
`An index of ${index} returns the character ${sentence.at(index)}`;
// "An index of 5 returns the character u"
Index 5 lands on "u" in "quick" (after "The "). Counting always starts at 0.
Example 2 — Negative Index
Count backward from the end of the same sentence.
JavaScript
const sentence = "The quick brown fox jumps over the lazy dog.";
const index = -4;
`An index of ${index} returns the character ${sentence.at(index)}`;
// "An index of -4 returns the character d"
charAt treats bad indexes as empty text. at uses undefined for misses and supports negative positions.
Applications
🚀 Common Use Cases
Last character checks — file extensions, invoice suffixes, trailing punctuation.
Readable relative indexing — at(-2) instead of length - 2.
Validation — detect missing positions with === undefined.
Teaching indexes — pair with length for beginners.
Array twin — same mental model as array.at(-1).
Not for full emoji — use code points / segmenters when graphemes matter.
🧠 How at() Resolves an Index
1
Receive an index
Positive from the start, or negative from the end.
Input
2
Normalize the position
Negative values become length + index.
Resolve
3
Read one code unit
Return that character as a new string.
Read
4
✅
Or return undefined
If the resolved index is outside 0 … length - 1.
Important
📝 Notes
at() returns one UTF-16 code unit, not always one visible emoji.
Out-of-range indexes return undefined, not "".
charAt(-1) is not the last character — use at(-1).
Fractional indexes are truncated toward zero (like other string index methods).
Empty string: "".at(0) and "".at(-1) are both undefined.
Prefer at for new code when you need relative indexing.
Compatibility
Browser & Runtime Support
String.prototype.at() is Baseline Widely available — supported in modern browsers (from around March 2022) and current Node.js.
✓ Baseline · Widely available
String.at()
Safe for modern apps. Prefer at(-1) over length - 1 for last-character access.
Modern+Widely available
Google ChromeSupported · Desktop & Mobile
Full support
Mozilla FirefoxSupported · Desktop & Mobile
Full support
Apple SafariSupported · macOS & iOS
Full support
Microsoft EdgeSupported · Chromium
Full support
Internet ExplorerNo native support · Use a polyfill
Polyfill
OperaSupported · Modern versions
Full support
Samsung InternetSupported · Android
Full support
BunSupported · JavaScript runtime
Supported
DenoSupported · JavaScript runtime
Supported
Node.jsSupported · Server runtime
Supported
Android WebViewSupported · Modern WebView
Full support
at()Excellent
Bottom line: Use String.at() for positive and negative indexes. Remember out-of-range returns undefined, and emoji may span two code units.
Wrap Up
Conclusion
String.prototype.at() is the clearest way to read a character by relative index — especially at(-1) for the last character — with undefined when the position does not exist.
Pair with length when explaining zero-based indexes
Use code-point helpers for full emoji characters
❌ Don’t
Expect charAt(-1) to behave like at(-1)
Assume at(0) on an emoji returns the whole emoji
Treat out-of-range at like an empty string
Use str[-1] for end access
Forget strings are immutable — at never edits in place
Summary
Key Takeaways
Knowledge Unlocked
Five things to remember about String.at()
Relative indexing for string characters.
5
Core concepts
📝01
Returns
1 unit / undefined
API
🔙02
End
at(-1)
Pattern
✓03
Negatives
supported
Feature
⚡04
vs charAt
clearer
Compare
📄05
Mutates
no
Immutable
❓ Frequently Asked Questions
String.prototype.at(index) returns the UTF-16 code unit at that position as a one-character string. Positive indexes count from the start; negative indexes count from the end. Out-of-range indexes return undefined.
charAt() does not support negative indexes — charAt(-1) returns an empty string. at(-1) returns the last character. Out of range, charAt returns "" while at returns undefined.
Bracket access also fails for negatives (str[-1] is undefined for a different reason — it looks up a property named "-1"). at(-1) is the clear way to read from the end.
at() returns one UTF-16 code unit. Many emoji use two code units (a surrogate pair), so at(0) on an emoji may return only half. Use codePointAt() or [...str] when you need full code points.
No. Strings are immutable. at() returns a new one-character string (or undefined).
It is Baseline Widely available (supported across modern browsers since around March 2022) and in current Node.js releases.
Did you know?
String.prototype.at() and Array.prototype.at() were designed together so strings and arrays share the same relative-index mental model — item.at(-1) means “last element” in both places.