javascript中string类型处理unicode需区分utf-16编码单元与unicode码点:bmp字符占1单元,辅助平面字符用代理对(2单元);应使用codepointat/fromcodepoint/for-of等码点级api替代charcodeat/fromcharcode/传统for循环。

JavaScript 中 String 类型对 Unicode 的处理,核心在于区分「UTF-16 编码单元」和「Unicode 码点」。字符串底层用 UTF-16 存储,BMP 字符(如普通汉字、英文字母)占 1 个单元,而 emoji、古文字等辅助平面字符(码点 > U+FFFF)需用代理对(2 个单元)表示。直接用 .length 或 .charCodeAt() 容易出错,必须使用 ES6+ 提供的码点级 API 才能正确操作。
获取真实码点:用 codePointAt 而非 charCodeAt
charCodeAt(i) 只返回第 i 个 UTF-16 单元的值,遇到代理对会拆开高位/低位,结果不可靠。例如 '?'.charCodeAt(0) 返回 55356(高位代理),不是完整码点。
- 改用
str.codePointAt(i):返回位置 i 开始的完整 Unicode 码点,自动识别代理对 - 它支持跳过代理对的第二个单元,所以遍历时建议配合
i += str[i] === undefined ? 2 : 1或直接用 for-of - 返回值是十进制整数,比如
'?'.codePointAt(0)→128713(即0x1F6EC)
生成字符:优先用 fromCodePoint 替代 fromCharCode
String.fromCharCode() 最多只能处理 0–65535(U+FFFF)范围内的数值,传入 emoji 码点(如 128713)会得到乱码或替换符 ▯。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
String.fromCodePoint(128713)→'?',原生支持所有 Unicode 码点(U+0000–U+10FFFF) - 可一次传入多个码点:
String.fromCodePoint(0x4F60, 0x597D, 0x1F600)→'你好?' - 若需兼容旧环境,可用 polyfill 或先判断码点是否超限再分拆为代理对
遍历与拆分:用 for-of 或 Array.from 替代传统 for 循环
传统 for (let i = 0; i 配合 <code>str[i] 或 charAt(i) 会把代理对当成两个独立“字符”,导致截断或渲染异常。
-
for (const ch of str):原生按码点迭代,ch每次都是一个完整逻辑字符 -
Array.from(str)或[...str]:将字符串正确拆分为 Unicode 字符数组,长度即真实字符数 - 例如
Array.from('??').length是1,而'??'.length是4(含 ZWJ 和多个代理对)
正则匹配:必须加 u 标志才能正确识别 Unicode
默认正则引擎按 UTF-16 单元解析,/./ 匹配不了 emoji,/\w+/ 也匹配不到中文或带音标的字母。
- 启用
u标志后,/./u.test('?')→true,/^\p{Emoji}$/u可精准匹配 emoji -
\p{Script=Han}、\p{Letter}等 Unicode 属性类必须配合u使用 - 字符串替换、提取时也需带上
u,否则'a\u0301'.replace(/./g, 'x')会把基础字符和组合标记分开处理
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










