Unicode码点是字符唯一标识,U+0000–U+FFFF用UTF-16单码元表示,U+10000以上需代理对;应使用codePointAt()、fromCodePoint()、for…of及u标志正则等码点级API,避免charCodeAt()等导致的误判。

Unicode 字符和码点不是一一对应的“单字节映射”,而是存在组合、代理、规范化等多层关系。处理字符串时,若只用 .charCodeAt() 或 ord() 这类基础方法,容易漏掉增补平面字符(如 emoji、生僻汉字)或组合字符(如带声调的拉丁字母),导致长度误判、截断错误、搜索失败等问题。
码点(Code Point)才是字符的真正身份
每个 Unicode 字符背后是一个唯一的码点,格式为 U+XXXXX(如 “中” 是 U+4E2D,“?” 是 U+20BB7)。注意:码点 ≠ 存储单位,也 ≠ 屏幕上看到的一个“字形”。
- 码点是逻辑概念,代表抽象字符;而 UTF-8/UTF-16/UTF-32 是编码方式,负责把码点转成字节序列
- U+0000–U+FFFF 在基本多文种平面(BMP),可被 UTF-16 单个 16 位码元表示;U+10000 及以上需代理对(surrogate pair)
- 像 ??(程序员 emoji)实际由多个码点组成:U+1F468 + U+200D + U+1F4BB,属于“字形集群”(grapheme cluster),不是单个字符
JavaScript 中正确获取与生成码点
旧方法 String.fromCharCode() 和 .charCodeAt() 最多处理 16 位(0–65535),遇到 U+20BB7 这类四字节字符会截断高位,返回错误结果。
- 用
String.fromCodePoint(0x20BB7)替代String.fromCharCode() - 用
'?'.codePointAt(0)替代'?'.charCodeAt(0),它能完整返回 0x20BB7 - 遍历字符串所有码点,应使用
for…of循环(按码点迭代),而非for (let i=0; i<s.length; i++)(按 UTF-16 码元索引)
Python 中的字符串即 Unicode 序列
Python 3 的 str 类型原生支持 Unicode,len() 返回的是码点数量(不是字节数),但要注意组合字符和 emoji 的实际显示宽度。
-
ord('中')→ 20013(即 0x4E2D);chr(20013)→ '中' - 处理 emoji 或带修饰符字符(如 ??)时,
list('??')返回两个元素:['\U0001F469', '\U0001F3FB'],说明它是两个码点的组合 - 需要按“用户感知的字符”切分(比如光标移动一格),得借助
grapheme库或unicodedata模块做正规化与分段
统一与安全:normalize() 和正则中的 Unicode 意识
同一个视觉字符可能有多种码点组合方式。例如 “é” 可以是单个预组字符 U+00E9,也可以是 U+0065(e)+ U+0301(重音符)。不正规化就直接比较或搜索,会出错。
- 用
'é'.normalize('NFC') === '\u0065\u0301'.normalize('NFC')判断是否等价 - 正则表达式中启用 Unicode 模式:
/\p{Script=Han}/u匹配汉字,/\p{Emoji}/u匹配 emoji - 避免用
.split('')分割含组合符的字符串;改用[...str](ES2015 扩展运算符)或Array.from(str),它们按码点拆分

















