根据 JavaScript - 权威指南,
JavaScript假定它正在解释的源代码已经规范化,并且没有尝试规范化标识符,字符串或正则表达式本身。
Unicode标准定义了所有字符的首选编码,并指定了将文本转换为适合比较的规范形式的规范化过程。
如果JS没有规范化Unicode,那么谁来做它以及什么时候?
如果JavaScript没有规范化Unicode,那么
是怎样的"café" === "caf\u00e9" // => true
为什么
"café" === "cafe\u0301" // => false
由于两者(\u00e9
和e\u0301
)都是Unicode方式来形成é。
答案 0 :(得分:3)
您正在混淆unicode规范化和字符串转义。
"café"
...是由code points 0x63,0x61,0x66,0xe9的字符组成的字符串。
您可以使用转义表示
来获取完全相同的字符串"caf\u00e9"
// or even
"\u0063\u0061\u0066\u00e9"
// or why not
"\u0063\u0061fé"
当读取这样的字符串时,javascript un-escapes字符串。也就是说,它用匹配的字符替换转义序列。这是用新行替换“\ n”的完全相同的过程。
现在,你的第二个例子实际上是另一个字符串,因为它没有规范化。它是由字符0x63,0x61,0x66,0x65,0x301组成的字符串。由于没有发生规范化,因此它不是相同的字符串。
现在尝试使用相同的字符串,使用您无法使用键盘输入的序列,但我会在此复制粘贴:"café"
。现在测试一下:
> a = "café" // this one is copy-pasted with the combining acute
> b = "café" // this one is typed using the "é" key on my keyboard
> a === "cafe\u0301"
<- true
> b === "cafe\u0301"
<- false
> a === "caf\u00e9"
<- false
> b === "caf\u00e9"
<- true
> a === b
<- false
// Now just making sure...
> a.length
<- 5
> b.length
<- 4
“café”和“café”呈现相同的事实并不能使它们成为相同的字符串。 JavaScript会比较字符串,发现0x63, 0x61, 0x66, 0xe9
与0x63, 0x61, 0x66, 0x65, 0x301
不同并返回false。