codepointat 正确获取完整 unicode 码点,charcodeat 仅返回 utf-16 编码单元;前者能处理 emoji 等增补平面字符,后者对代理对只能分别读取高低位,无法还原原始码点。

codePointAt 和 charCodeAt 都用于获取字符串中指定位置字符的编码值,但它们处理 Unicode 的方式不同:前者支持完整的 Unicode 码点(包括增补平面字符,如 emoji 或古文字),后者只返回 UTF-16 编码单元(可能产生代理对中的单个 16 位值,无法正确表示大于 0xFFFF 的字符)。
charCodeAt:只取 UTF-16 编码单元
charCodeAt(index) 返回字符串中索引位置处的 UTF-16 编码单元(0–65535)。对于基本多文种平面(BMP)字符(U+0000–U+FFFF),它能准确返回码点;但对于超出 BMP 的字符(如 ?、??、古汉字),它们在 JavaScript 字符串中以两个 16 位的“代理对”(surrogate pair)形式存储,charCodeAt 只能分别读取其中的高代理或低代理单元,无法还原原始码点。
-
'A'.charCodeAt(0)→ 65 -
'?'.charCodeAt(0)→ 55362(高代理,0xD842) -
'?'.charCodeAt(1)→ 56647(低代理,0xDFB7) - 单独看这两个值,无法得知原字符是 U+20BB7(?)
codePointAt:正确获取完整 Unicode 码点
codePointAt(index) 是 ES6 新增方法,能识别代理对并自动组合,返回完整的 Unicode 码点(可超过 65535)。若索引指向代理对的高代理位,它会连同下一个低代理位一起计算;若索引指向低代理位或无效位置,则只返回该单元值(不组合)。
-
'A'.codePointAt(0)→ 65 -
'?'.codePointAt(0)→ 134071(即0x20BB7,正确码点) -
'?'.codePointAt(1)→ 56647(低代理本身不是独立字符,返回其编码单元) -
'??'.codePointAt(0)→ 返回第一个组成码点(通常是基础人像),但注意这是带 ZWJ 的序列,实际由多个码点组合,codePointAt仍按单个码点位置读取(非按视觉字符计数)
实际使用建议
日常开发中应优先用 codePointAt 替代 charCodeAt,尤其当字符串可能含 emoji、中文扩展 B/C 区字符、数学符号等非 BMP 字符时。配合 String.fromCodePoint() 可实现安全的编解码往返。
- 遍历字符串获取所有码点:用
for…of或Array.from(str).map(ch => ch.codePointAt(0)),避免手动索引 +codePointAt(i)因代理对导致重复或跳过 - 判断是否为有效代理对起始位置?不必手动判断 —
codePointAt已内置逻辑 - 兼容旧环境?需用 polyfill 或转义处理(如正则
/[\uD800-\uDFFF]/g检测代理对)
小结:关键区别一句话
charCodeAt 按 UTF-16 “内存单元”取值,codePointAt 按 Unicode “抽象字符”取值;只要关心字符本意(比如比较、转换、国际化),就该用后者。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











