JS Unicode 模式下的行为
启用 Unicode 模式后,正则按码点而不是按 UTF-16 码元处理文本:量词与点号作用于完整字符,字符类按码点匹配,属性转义才可用。不启用时,一个补充平面字符会被当成两个单位,字符数量统计、截断与匹配结果都会与直觉不同,而且属性转义不会报错,会静默变成字面文本匹配。
基本信息
| 字符单位 | 未启用时按码元,启用后按码点,影响点号与量词的作用对象 |
|---|---|
| 属性转义 | 仅在启用后可用,可写脚本或类别属性 |
| 转义严格度 | 启用后转义规则更严格,部分宽松写法会直接报语法错误 |
| 互斥标志 | 另有一种面向字符类集合运算的标志,与它互斥,不能同时使用 |
典型使用场景
- 含表情符号的输入:校验、截断、计数都必须按码点处理才能避免截断到半个字符
- 按文字系统校验:判断是否为某语言字符集,需要属性转义
- 扩展区汉字处理:生僻字位于补充平面,未启用模式时长度与匹配都异常
- 长度限制:按字符数限制输入长度时,需要与实际字符单位一致
- 集合运算场景:对字符类做交并差时使用另一种标志,注意与它互斥
行为实测
行为实测
/^.$/.test('\u{1F600}'); // false:未启用时表情占两个码元
/^.$/u.test('\u{1F600}'); // true:启用后按码点处理
'\u{20000}'.length; // 2:字符串长度按码元计算
/\p{Han}/u.test('中'); // 报属性名非法:JS 要求写完整属性名
/\p{Script=Han}/u.test('中'); // true:启用模式并写完整属性名
/\p{Han}/.test('p{Han}'); // true:未启用时属性转义退化为字面文本匹配
/[\u{1F600}-\u{1F64F}]/u.test('\u{1F600}'); // 启用后可在字符类里按码点写区间启用前后的差异
| 项目 | 未启用 | 启用后 |
|---|---|---|
| 字符单位 | UTF-16 码元 | 码点 |
| 点号与量词 | 可能拆开一个字符 | 作用于完整字符 |
| 属性转义 | 被当成字面文本,不报错 | 可用,需写完整属性名 |
| 非法转义 | 多数被当作字面量 | 直接报语法错误 |
| 字符类合并运算 | 不支持 | 需使用另一种互斥标志 |
启用 Unicode 模式不会扩大简写类的覆盖范围:单词类与数字类仍按 ASCII 解释,要匹配汉字或其他语言字母必须改用属性转义或显式区间,这一点与直觉相反。
启用后建议对全部既有模式跑一遍回归:原先依赖宽松转义的写法可能直接报错,尤其是字符类中的连字符与反斜杠位置。