String.prototype.normalize()

normalize()String 值的方法,它返回此字符串的 Unicode 规范化形式。

试试

语法

js
normalize()
normalize(form)

参数

form 可选

"NFC""NFD""NFKC""NFKD" 之一,指定 Unicode 规范化形式。如果省略或为 undefined,则使用 "NFC"

这些值具有以下含义

"NFC"

规范分解,然后是规范组合。

"NFD"

规范分解。

"NFKC"

兼容分解,然后是规范组合。

"NFKD"

兼容分解。

返回值

包含给定字符串的 Unicode 规范化形式的字符串。

异常

RangeError

如果 form 不是上述值之一,则抛出。

描述

Unicode 为每个字符分配了一个唯一的数值,称为码点。例如,"A" 的码点为 U+0041。但是,有时多个码点或码点序列可以表示同一个抽象字符——例如字符 "ñ" 可以用以下任一表示

  • 单个码点 U+00F1。
  • "n" (U+006E) 的码点后跟组合波浪号 (U+0303) 的码点。
js
const string1 = "\u00F1";
const string2 = "\u006E\u0303";

console.log(string1); // ñ
console.log(string2); // ñ

但是,由于码点不同,字符串比较不会将它们视为相等。由于每个版本中的码点数量不同,它们甚至具有不同的长度。

js
const string1 = "\u00F1"; // ñ
const string2 = "\u006E\u0303"; // ñ

console.log(string1 === string2); // false
console.log(string1.length); // 1
console.log(string2.length); // 2

normalize() 方法通过将字符串转换为所有表示相同字符的码点序列共有的规范化形式来帮助解决此问题。主要有两种规范化形式,一种基于规范等价,另一种基于兼容性

规范等价规范化

在 Unicode 中,两个码点序列如果表示相同的抽象字符,并且应该始终具有相同的视觉外观和行为(例如,它们应该始终以相同的方式排序),则具有规范等价。

您可以使用 "NFD""NFC" 参数使用 normalize() 来生成所有规范等价字符串都相同的字符串形式。在下面的示例中,我们规范化了字符 "ñ" 的两种表示形式

js
let string1 = "\u00F1"; // ñ
let string2 = "\u006E\u0303"; // ñ

string1 = string1.normalize("NFD");
string2 = string2.normalize("NFD");

console.log(string1 === string2); // true
console.log(string1.length); // 2
console.log(string2.length); // 2

组合形式和分解形式

请注意,"NFD" 下规范化形式的长度为 2。这是因为 "NFD" 提供了规范形式的分解版本,其中单个码点被拆分为多个组合码点。"ñ" 的分解规范形式为 "\u006E\u0303"

您可以指定 "NFC" 来获取组合规范形式,其中多个码点在可能的情况下被替换为单个码点。"ñ" 的组合规范形式为 "\u00F1"

js
let string1 = "\u00F1"; // ñ
let string2 = "\u006E\u0303"; // ñ

string1 = string1.normalize("NFC");
string2 = string2.normalize("NFC");

console.log(string1 === string2); // true
console.log(string1.length); // 1
console.log(string2.length); // 1
console.log(string2.codePointAt(0).toString(16)); // f1

兼容规范化

在 Unicode 中,两个码点序列如果表示相同的抽象字符,并且在某些(但不一定所有)应用程序中应该被视为一样,则它们是兼容的。

所有规范等价序列也是兼容的,但反之则不然。

例如

  • 码点 U+FB00 表示 连字 "ff"。它与两个连续的 U+0066 码点 ("ff") 兼容。
  • 代码点 U+24B9 代表符号 "Ⓓ"。它与 U+0044 代码点("D")兼容。

在某些方面(如排序)它们应该被视为等效的,而在某些方面(如视觉外观)它们不应该被视为等效的,因此它们不是规范等效的。

可以使用 normalize() 方法,并使用 "NFKD""NFKC" 参数来生成所有兼容字符串的相同形式。

js
let string1 = "\uFB00";
let string2 = "\u0066\u0066";

console.log(string1); // ff
console.log(string2); // ff
console.log(string1 === string2); // false
console.log(string1.length); // 1
console.log(string2.length); // 2

string1 = string1.normalize("NFKD");
string2 = string2.normalize("NFKD");

console.log(string1); // ff <- visual appearance changed
console.log(string2); // ff
console.log(string1 === string2); // true
console.log(string1.length); // 2
console.log(string2.length); // 2

在应用兼容规范化时,重要的是要考虑你打算对字符串做什么,因为规范化后的形式可能不适用于所有应用程序。在上面的例子中,规范化适用于搜索,因为它允许用户通过搜索 "f" 来找到字符串。但它可能不适用于显示,因为视觉表示不同。

与规范规范化一样,可以通过分别传递 "NFKD""NFKC" 来请求分解或组合的兼容形式。

示例

使用 normalize() 方法

js
// Initial string

// U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE
// U+0323: COMBINING DOT BELOW
const str = "\u1E9B\u0323";

// Canonically-composed form (NFC)

// U+1E9B: LATIN SMALL LETTER LONG S WITH DOT ABOVE
// U+0323: COMBINING DOT BELOW
str.normalize("NFC"); // '\u1E9B\u0323'
str.normalize(); // same as above

// Canonically-decomposed form (NFD)

// U+017F: LATIN SMALL LETTER LONG S
// U+0323: COMBINING DOT BELOW
// U+0307: COMBINING DOT ABOVE
str.normalize("NFD"); // '\u017F\u0323\u0307'

// Compatibly-composed (NFKC)

// U+1E69: LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
str.normalize("NFKC"); // '\u1E69'

// Compatibly-decomposed (NFKD)

// U+0073: LATIN SMALL LETTER S
// U+0323: COMBINING DOT BELOW
// U+0307: COMBINING DOT ABOVE
str.normalize("NFKD"); // '\u0073\u0323\u0307'

规范

规范
ECMAScript 语言规范
# sec-string.prototype.normalize

浏览器兼容性

BCD 表格只在浏览器中加载

另请参见