String.prototype.normalize() 是解决 Unicode 等价性问题的核心方法,支持 NFC、NFD、NFKC、NFKD 四种标准化形式,分别适用于显示存储、底层处理、搜索匹配和文本清洗,但不处理简繁体等非等价字符。

String.prototype.normalize() 是 JavaScript 中处理 Unicode 等价性问题的核心方法,尤其在多语言文本比对、搜索、去重或标准化存储时,能有效解决“看起来一样、但码点不同”的字符判定难题(比如带重音符号的拉丁字母、东亚表意文字的兼容形式、阿拉伯语连字变体等)。
理解 Unicode 等价性:合成形 vs 分解形
Unicode 允许同一个字符用多种方式编码。典型例子是 é:
- 预组字符(合成形):
'\u00e9'(U+00E9,LATIN SMALL LETTER E WITH ACUTE) - 基础字符 + 组合标记(分解形):
'e\u0301'(U+0065 + U+0301,即 e + COMBINING ACUTE ACCENT)
两者视觉和语义完全相同,但字符串字面值不同,直接 === 比较会返回 false。normalize() 可将它们统一为同一种形式,实现语义一致的判定。
四种标准化形式及其适用场景
normalize() 接受一个参数('NFC'、'NFD'、'NFKC'、'NFKD'),关键区别在于是否处理“兼容等价”:
- NFC(默认):合成规范形。优先使用预组字符,适合显示、存储和一般比对(如用户输入校验、数据库索引)
- NFD:分解规范形。把所有可分解字符拆为基础+组合标记,便于底层文本处理(如音标分析、光标定位)
- NFKC:合成兼容形。除规范等价外,还处理兼容等价(如全角/半角 ASCII、上标数字、罗马数字),适合搜索与模糊匹配
- NFKD:分解兼容形。NFKC 的分解版,常用于清洗(如移除变音符号、统一标点宽度)
实际应用:多语言文本标准化比对
例如处理法语、越南语、日语混合输入:
// 用户可能输入不同形式的 'café' 或 '한국어'
const input1 = 'café'; // NFC 形式
const input2 = 'cafe\u0301'; // NFD 形式
const input3 = '한국어'; // 韩文(本身无合成/分解问题,但可能含兼容字符)
// 统一用 NFC 标准化后比较
input1.normalize('NFC') === input2.normalize('NFC'); // true
// 搜索时放宽要求:忽略全角/半角、上标等差异
const searchQuery = '1st';
const text = '1ˢᵗ'; // 上标 st
searchQuery.normalize('NFKC') === text.normalize('NFKC'); // true
注意事项与常见陷阱
- normalize() 不改变原始字符串,返回新字符串,需显式赋值或链式调用
- 不是所有语言都严格依赖 NFC/NFD;中文简繁体、日文汉字异体字属于不同码点,normalize 无法处理,需额外映射表
- 部分组合标记(如某些阿拉伯语上下文敏感连字)可能不被完全分解,需结合 ICU 库或 Intl API 做更深层处理
- 性能敏感场景(如高频比对)建议缓存 normalize 结果,避免重复计算

















