ES6 中正确解析字符串的16进制Unicode编码需区分码点与UTF-16编码单元:用\u{...}表示任意码点,codePointAt()读取完整码点,String.fromCodePoint()反向生成字符,避免ES5中charCodeAt()/fromCharCode()的截断问题。

ES6 中正确解析字符串的 16 进制 Unicode 编码,关键在于区分“码点(code point)”和“UTF-16 编码单元(code unit)”,并使用 ES6 新增的语法与 API 来避免传统方式的截断或误读。
用 \u{...} 表示任意码点
ES5 只支持 \uXXXX(4 位十六进制),只能表示 U+0000–U+FFFF 范围内的字符(即基本多语种平面 BMP)。超出范围的码点(如 U+20BB7、U+1F680)若直接写成 \u20BB7,JS 会错误解析为 \u20BB + 7,导致乱码或意外字符。
ES6 引入大括号语法,明确标识完整码点:
-
"\u{41}"→"A" -
"\u{20BB7}"→"?"(不是乱码) -
"\u{1F680}"→"?" - 支持补零或不补零:
"\u{41}\u{42}\u{43}"和"\u{0041}\u{0042}\u{0043}"效果相同
用 codePointAt() 读取真实码点
ES5 的 charCodeAt() 每次只读一个 UTF-16 编码单元(2 字节),对辅助平面字符(如 "?")会拆成两个值(55362 和 57271),无法还原原始码点。
codePointAt() 按逻辑字符位置读取完整码点(32 位整数):
-
"?".codePointAt(0)→134071(即0x20BB7) -
"?a".codePointAt(0)→134071;.codePointAt(2)→97("a"的码点) - 返回值是十进制,可用
.toString(16)转为十六进制:(134071).toString(16)→"20bb7"
用 String.fromCodePoint() 反向生成字符
ES5 的 String.fromCharCode() 仅接受 16 位数值,传入 0x20BB7 会截断为低 16 位(0xBB7),输出错误字符。
String.fromCodePoint() 支持完整 Unicode 码点:
-
String.fromCodePoint(0x20BB7)→"?" -
String.fromCodePoint(0x1F680, 0x1F681)→"??" - 可传入多个码点,自动拼接成字符串
遍历与判断需配合新特性
传统 for (let i = 0; i 或 <code>charAt() 仍按编码单元遍历,对辅助平面字符会“切开”一个逻辑字符。
推荐方式:
- 用
for...of遍历:for (const ch of "?abc") { console.log(ch); }→ 正确输出 4 个字符 - 用
at()安全取字符:"?".at(0)→"?"(ES2022,但广泛兼容) - 判断包含/起始/结束:
str.includes("\u{20BB7}")、str.startsWith("\u{1F680}")更直观可靠


















