codePointAt 是正确处理四字节 Unicode 字符的关键方法,它自动识别代理对并返回完整码点,而 charCodeAt 仅返回单个 UTF-16 编码单元值,无法还原真实码点。

JavaScript 中的 codePointAt 方法是正确处理四字节 Unicode 字符(即码点大于 0xFFFF 的字符,如 emoji、部分汉字、古文字等)的关键工具。它解决了传统 charCodeAt 在处理代理对(surrogate pair)时只能返回单个 16 位值、无法还原真实码点的问题。
为什么需要 codePointAt 而不是 charCodeAt
charCodeAt 每次只读取一个 UTF-16 编码单元(16 位),而四字节 Unicode 字符(U+10000 及以上)在 JavaScript 字符串中以两个连续的 UTF-16 编码单元(即代理对:高位代理 + 低位代理)存储。例如字符 "?"(U+20BB7)在内存中占两个位置:
-
"?".length === 2(不是 1) -
"?".charCodeAt(0) === 0xD842(高位代理) -
"?".charCodeAt(1) === 0xDFB7(低位代理) - 单独看这两个值毫无语义,也无法直接拼出
0x20BB7
codePointAt 则自动识别代理对,并返回完整的 21 位 Unicode 码点(如 "?".codePointAt(0) === 0x20BB7),无需手动判断或组合。
codePointAt 的基本用法和返回值
调用 str.codePointAt(index) 时,index 指向字符串中 UTF-16 编码单元的位置(从 0 开始)。方法返回对应码点的十进制数值,若越界则返回 undefined:
"a".codePointAt(0) → 97-
"?".codePointAt(0) → 134071(即0x20BB7) -
"?".codePointAt(1) → 57271(即低位代理值,但这是“跳过”代理对后的结果;实际应始终从首代理位置调用) -
"?".codePointAt(2) → undefined(超出长度)
注意:对四字节字符,只需对第一个位置(即高位代理所在索引)调用 codePointAt,它会自动处理后续代理单元;无需、也不应再对下一个索引重复调用。
配合 for…of 循环安全遍历所有字符
传统 for (let i = 0; i 遍历的是 UTF-16 编码单元,会导致四字节字符被拆成两次迭代。更可靠的方式是使用 for…of,它按 Unicode 字符(即码点)而非编码单元遍历:
for (const ch of "Hello??") { console.log(ch, ch.codePointAt(0).toString(16)); }- 输出依次为:
"H"→68、"e"→65、…、"?"→20bb7、"?"→1f30d - 内部机制正是基于
codePointAt和字符串迭代器实现的
兼容性与替代方案(仅限旧环境)
codePointAt 自 ES2015(ES6)起原生支持,现代浏览器和 Node.js 均可用。若需兼容极老环境(如 IE),可手动实现代理对检测:
codePointAt
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











