codePointAt 能正确处理多字节 Unicode 字符,因它自动识别代理对并返回完整码点;而 charCodeAt 仅返回单个码元值,无法还原超出 BMP 的字符。

JavaScript 的 codePointAt 方法原生支持多字节 Unicode 字符(即码点 ≥ U+10000 的字符),是处理 emoji、古汉字、部分少数民族文字等四字节 UTF-16 字符的正确方式。
为什么 charCodeAt 不够用
JavaScript 字符串内部用 UTF-16 编码,常规字符(U+0000–U+FFFF)占 1 个码元(2 字节),而超出基本多语言平面(BMP)的字符(如 ? U+20BB7、? U+1F44B)需用两个连续码元表示——称为代理对(surrogate pair):
-
"?".length === 2(不是 1) -
"?".charCodeAt(0) → 55362(高位代理,D842) -
"?".charCodeAt(1) → 57271(低位代理,DFB7) - 单独看这两个值无法还原真实字符,也无法直接拼出
0x20BB7
codePointAt 如何正确识别多字节字符
该方法自动检测代理对,并返回完整的 21 位 Unicode 码点(十进制):
-
"?".codePointAt(0) → 134071(即0x20BB7) - 只需对高位代理所在索引调用一次,它会自动跳过下一个码元
-
"?a".codePointAt(0) → 134071,.codePointAt(2) → 97(对应 'a') - 若传入低位代理位置(如
.codePointAt(1)),它只返回该码元本身值(57271),不作代理对解析
安全遍历多字节字符的推荐方式
避免手动计算索引偏差,改用语义正确的迭代方式:
立即学习“Java免费学习笔记(深入)”;
for (const ch of "Hello??") { console.log(ch, ch.codePointAt(0).toString(16)); }- 扩展运算符:
[..."Hello??"].map(ch => ch.codePointAt(0)) - 两者都按“字符”而非“码元”分割,天然兼容代理对
实用辅助判断
可快速区分字符是否为多字节(即是否属于辅助平面):
function isAstral(c) { return c.codePointAt(0) > 0xFFFF; }-
isAstral("?") → true,isAstral("a") → false - 配合
String.fromCodePoint可双向转换:String.fromCodePoint(0x20BB7) === "?"


















