String.prototype.charCodeAt()
Returns the numeric UTF-16 code unit value of the character at a given index, or NaN if out of range.
charCodeAt(index)- Added in JavaScript ECMAScript 1
Parameters
| Parameter | Type | Description |
|---|---|---|
$index | number | Zero-based index of the character whose code unit is returned. Converted to an integer; undefined becomes 0. |
Return value
numberAn integer between 0 and 65535 representing the UTF-16 code unit at the given index, or NaN when the index is outside 0 – str.length - 1.
charCodeAt() converts a character to its numeric UTF-16 code unit, the inverse of String.fromCharCode(). It is the workhorse behind hand-rolled hashes, checksums, character-class tests and any code that needs arithmetic on letters.
The 16-bit ceiling
The return value never exceeds 65535. Characters above U+FFFF are stored as two code units, so charCodeAt() gives you a surrogate half: a leading surrogate in the range 0xD800–0xDBFF or a trailing one in 0xDC00–0xDFFF. Neither is a usable character on its own. Use codePointAt() when the input can contain emoji, rare CJK, or mathematical alphanumerics.
NaN, not an exception
An out-of-range index returns NaN, which then poisons every arithmetic operation downstream — a running total becomes NaN and stays there. Check with Number.isNaN(), or bound the loop with str.length.
Common comparisons
For ASCII ranges, comparing code units is faster and clearer than a regular expression: const c = s.charCodeAt(i); c >= 48 && c <= 57 tests for a digit. Remember it is a code-unit comparison, not a locale-aware one — for sorting human-readable text use Intl.Collator instead.
Example
When to use it
- Build a fast non-cryptographic string hash for cache keys
- Classify a character as a digit or ASCII letter without a regex
- Implement a Caesar or ROT13 shift over letters
- Detect surrogate halves before handing text to a legacy encoder
Frequently asked questions
How do I get the ASCII value of a character in JavaScript?
Call str.charCodeAt(index), which returns the UTF-16 code unit — identical to the ASCII value for characters below 128. String.fromCharCode() converts back.
Why does charCodeAt() return 55357 for an emoji?
Because emoji above U+FFFF are stored as a surrogate pair and charCodeAt() only ever returns one 16-bit code unit. Use codePointAt() to get the full code point in one call.
What does charCodeAt() return for an invalid index?
It returns NaN instead of throwing. Test with Number.isNaN(), since NaN silently propagates through any arithmetic that follows.
More examples
A small string hash
Each code unit feeds a rolling multiply-add. The >>> 0 keeps the accumulator an unsigned 32-bit integer; without it the value drifts into floating point and loses precision on long strings.
function hash(str) {
let h = 0;
for (let i = 0; i < str.length; i++) {
h = (h * 31 + str.charCodeAt(i)) >>> 0; // keep it a uint32
}
return h;
}
console.log(hash("hello")); // 99162322
console.log(hash("hellp")); // 99162323
console.log(hash("")); // 0Shifting letters by code unit
Code-unit arithmetic shifts only the ASCII letter ranges; spaces and punctuation fall through untouched, and applying ROT13 twice restores the original.
const rot = (s, n) =>
[...s]
.map((ch) => {
const c = ch.charCodeAt(0);
if (c >= 97 && c <= 122) return String.fromCharCode(((c - 97 + n) % 26) + 97);
if (c >= 65 && c <= 90) return String.fromCharCode(((c - 65 + n) % 26) + 65);
return ch;
})
.join("");
console.log(rot("Attack at dawn!", 13)); // "Nggnpx ng qnja!"
console.log(rot(rot("Attack at dawn!", 13), 13)); // "Attack at dawn!"
Discussion