随着计算机在全球范围内的普及,Unicode 已成为处理文本的标准。但是,Unicode 中存在着多种写法,例如汉字“中”可以表示为 U+4E2D(CJK 统一汉字)或 U+9F8D(康熙字典中的一种写法)。这样会给字符串的比较、搜索、处理以及存储带来困难。因此,在 ECMAScript 2018(ES9)中引入了 Unicode 标准化(Normalization),以解决这些问题。
Unicode 标准化
Unicode 标准化的目的是将字符串的不同写法表示为同一标准形式,从而方便处理和存储。Unicode 标准提供了四种标准形式,也称为规范形式(Normalization Form):
NFC(Normalization Form Canonical Composition):组合字符。
NFD(Normalization Form Canonical Decomposition):分解字符。
NFKC(Normalization Form Compatibility Composition):组合字符并使得字符在语义上等价,例如:“à” 和 “á” 可以在 NFC 中表示为 “á ”。
NFKD(Normalization Form Compatibility Decomposition):分解字符并使得字符在语义上等价,例如:“à” 和 “á” 可以在 NFD 中表示为 “à”。
其中,NFC 和 NFD 叫做规范分解形式(Canonical Decomposition Form, CDF)和规范组合形式(Canonical Composition Form, CCF); NFKC 和 NFKD 叫做兼容分解形式(Compatibility Decomposition Form, CDF)和兼容组合形式(Compatibility Composition Form, CCF)。
字符串的标准化
字符串的标准化有两种方法:
String.prototype.normalize()
使用 String.prototype.normalize()
方法可以将字符串标准化为指定的形式。该方法接受一个标准形式的字符串参数,可选值为 "NFC"
,"NFD"
,"NFKC"
,"NFKD"
,默认值为 "NFC"
。
示例代码:
var str1 = '\u1E9B\u0323'; // 'ẛ̣' var str2 = str1.normalize(); console.log(str1 === str2); // false console.log(str2 === '\u1E69'); // true
Intl.Collator()
使用 Intl.Collator()
方法,可以创建一个与特定语言环境及选项相对应的字符串比较对象。其中,numeric
参数用于指定是否支持数字排序,默认为 false
,caseFirst
参数用于指定是否区分大小写,默认为 "false"
,可以设置为 "upper"
或 "lower"
,localeMatcher
参数用于指定寻找语言环境的算法,有 "lookup"
和 "best fit"
两种模式,分别对应精确匹配和模糊匹配,默认为 "best fit"
。
示例代码:
var arr = ['h', 'i', 'e', '\u00E9', 'a', 'b', '\u00C0', '\u00C1']; console.log(arr.sort(Intl.Collator('fr').compare)); // ['a', 'b', 'e', '\xE9', '\xC0', '\xC1', 'h', 'i'] console.log(arr.sort(Intl.Collator('fr', { sensitivity: 'base' }).compare)); // ['a', '\xC0', '\xC1', 'b', 'e', '\xE9', 'h', 'i']
优化性能
字符串的标准化会增加代码的执行时间,因此需要避免过度使用。对于只需要在本地或者当前字符编码中进行处理的字符,不需要进行标准化,例如在该字符编码中没有多种写法的英文字母或阿拉伯数字。
总结
Unicode 标准化在字符串处理中具有重要的作用,可以解决不同字符写法的比较、搜索、处理以及存储的问题,但是在使用时需要注意性能问题。使用 String.prototype.normalize()
方法和 Intl.Collator()
方法可以将字符串标准化为指定的形式,以及创建一个与特定语言环境及选项相对应的字符串比较对象,以便进行不同形式的字符串比较。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65a114eeadd4f0e0ff939533