问题 Node.js对Unicode的支持程度如何?


根据它 语言规范 JavaScript在Unicode中存在一些问题(如果我理解正确的话),因为文本总是作为一个内部由16位组成的字符处理。

JavaScript:好的部分 以类似的方式说出来。

当您在Google上搜索V8对UTF-8的支持时,您会得到相互矛盾的陈述。

那么:Node.js中的Unicode支持状态是什么(当问到这个问题时,当前版本是0.10.26)?它是否正确处理UTF-8所有可能的代码点,或者不是吗?

如果不是:有哪些可行的解决方法?


5759
2018-03-20 19:36


起源



答案:


你引用的两个来源, 语言规范 和克罗克福德的“JavaScript:好的部分”(第103页)说同样的话,虽然后者说得更简洁(显然,如果你已经知道这个话题)。作为参考我会引用Crockford:

JavaScript是在预计Unicode最多有65,536个字符的时候设计的。它已经发展到拥有超过100万个字符的容量。

JavaScript的字符是16位。这足以覆盖原始的65,536(现在称为基本多语言平面)。剩余的百万个字符中的每一个都可以表示为一对字符。 Unicode认为该对是单个字符。 JavaScript认为这对是两个截然不同的字符。

语言规范将16位单元称为“字符”和“代码单元”。另一方面,“Unicode字符”或“代码点”可以(在极少数情况下)需要表示两个16位“代码单元”。

所有JavaScript的字符串属性和方法,如 lengthsubstr()等等,使用16位“字符”(使用16位/ 32位Unicode字符,即UTF-16字符效率非常低)。例如,这意味着,如果你不小心,请 substr() 你可以单独留下32位UTF-16 Unicode字符的一半。只要您不显示JavaScript,JavaScript就不会抱怨,如果您这样做,甚至可能不会抱怨。这是因为,正如规范所说,JavaScript确实如此  检查字符是否有效UTF-16,它只是 假设 他们是。

在你的问题中,你问

[Node.js]是否正确处理UTF-8所有可能的代码点,或者不是吗?

由于所有可能的UTF-8代码点在输入之前都会在输入中转换为UTF-16(作为一个或两个16位“字符”),反之亦然,输出中的答案取决于“正确”的含义,但如果您接受JavaScript对此“正确”的解释,则答案为“是”。


10
2018-03-26 23:50





JavaScript字符串类型为UTF-16,因此其Unicode支持为100%。 所有 UTF 表单支持所有Unicode代码点。

以下是常见表格的一般细分:

  • UTF-8 - 8位代码单元;可变宽度(代码点为1-4代码单元)
  • UTF-16 - 16位代码单元;可变宽度(代码点为1-2个代码单元);大-尾数 或小端
  • UTF-32 - 32位代码单元;固定宽度; big-endian或little endian

当认为每个代码点适合16位时,UTF-16就会普及。此情况并非如此。 UTF-16后来被重新设计,允许代码点占用两个代码单元,旧版本重命名为UCS-2。 

然而,事实证明可见宽度无论如何都不能很好地与内存存储单元相提并论,因此UTF-16和UTF-32都具有有限的实用性。自然语言很复杂,在许多情况下,代码点序列以惊人的方式组合在一起。

“字符”的宽度测量取决于上下文。记忆?可见字素的数量?以像素为单位渲染宽度?

UTF-16仍然普遍使用,因为许多当今流行的语言/环境(Java / JavaScript / Windows NT)诞生于90年代。它没有破碎。但是,UTF-8通常是首选。

如果您遇到数据丢失/损坏问题,通常是因为代码转换器中存在缺陷或者误操作代码。


0
2018-03-20 20:12



但UTF-16与每个字符的16位完全不同:UTF-16动态使用16或32位,而JavaScript AFAIK静态使用16位。所以:恕我直言JavaScript不使用UTF-16,我提供的所有链接也告诉你。你有更新的消息来源吗? - Golo Roden
JavaScript中字符串的长度是代码的数量 单位 (每个都是16位宽,UTF-16。)代码 点 (如果您愿意,可以使用Unicode字符)可以是一个或两个代码 单位 在UTF-16中。所以单个代码 点 JavaScript中的长度为2。这就是UTF-16的工作原理。 JavaScript根据部分支持UTF-16 4.3.16 ECMA中的字符串值262。我认为你引用的作者批评UTF-16而不是JavaScript的UTF-16一致性。这就是字符串在C#和Java中的工作方式。 - McDowell


答案:


你引用的两个来源, 语言规范 和克罗克福德的“JavaScript:好的部分”(第103页)说同样的话,虽然后者说得更简洁(显然,如果你已经知道这个话题)。作为参考我会引用Crockford:

JavaScript是在预计Unicode最多有65,536个字符的时候设计的。它已经发展到拥有超过100万个字符的容量。

JavaScript的字符是16位。这足以覆盖原始的65,536(现在称为基本多语言平面)。剩余的百万个字符中的每一个都可以表示为一对字符。 Unicode认为该对是单个字符。 JavaScript认为这对是两个截然不同的字符。

语言规范将16位单元称为“字符”和“代码单元”。另一方面,“Unicode字符”或“代码点”可以(在极少数情况下)需要表示两个16位“代码单元”。

所有JavaScript的字符串属性和方法,如 lengthsubstr()等等,使用16位“字符”(使用16位/ 32位Unicode字符,即UTF-16字符效率非常低)。例如,这意味着,如果你不小心,请 substr() 你可以单独留下32位UTF-16 Unicode字符的一半。只要您不显示JavaScript,JavaScript就不会抱怨,如果您这样做,甚至可能不会抱怨。这是因为,正如规范所说,JavaScript确实如此  检查字符是否有效UTF-16,它只是 假设 他们是。

在你的问题中,你问

[Node.js]是否正确处理UTF-8所有可能的代码点,或者不是吗?

由于所有可能的UTF-8代码点在输入之前都会在输入中转换为UTF-16(作为一个或两个16位“字符”),反之亦然,输出中的答案取决于“正确”的含义,但如果您接受JavaScript对此“正确”的解释,则答案为“是”。


10
2018-03-26 23:50





JavaScript字符串类型为UTF-16,因此其Unicode支持为100%。 所有 UTF 表单支持所有Unicode代码点。

以下是常见表格的一般细分:

  • UTF-8 - 8位代码单元;可变宽度(代码点为1-4代码单元)
  • UTF-16 - 16位代码单元;可变宽度(代码点为1-2个代码单元);大-尾数 或小端
  • UTF-32 - 32位代码单元;固定宽度; big-endian或little endian

当认为每个代码点适合16位时,UTF-16就会普及。此情况并非如此。 UTF-16后来被重新设计,允许代码点占用两个代码单元,旧版本重命名为UCS-2。 

然而,事实证明可见宽度无论如何都不能很好地与内存存储单元相提并论,因此UTF-16和UTF-32都具有有限的实用性。自然语言很复杂,在许多情况下,代码点序列以惊人的方式组合在一起。

“字符”的宽度测量取决于上下文。记忆?可见字素的数量?以像素为单位渲染宽度?

UTF-16仍然普遍使用,因为许多当今流行的语言/环境(Java / JavaScript / Windows NT)诞生于90年代。它没有破碎。但是,UTF-8通常是首选。

如果您遇到数据丢失/损坏问题,通常是因为代码转换器中存在缺陷或者误操作代码。


0
2018-03-20 20:12



但UTF-16与每个字符的16位完全不同:UTF-16动态使用16或32位,而JavaScript AFAIK静态使用16位。所以:恕我直言JavaScript不使用UTF-16,我提供的所有链接也告诉你。你有更新的消息来源吗? - Golo Roden
JavaScript中字符串的长度是代码的数量 单位 (每个都是16位宽,UTF-16。)代码 点 (如果您愿意,可以使用Unicode字符)可以是一个或两个代码 单位 在UTF-16中。所以单个代码 点 JavaScript中的长度为2。这就是UTF-16的工作原理。 JavaScript根据部分支持UTF-16 4.3.16 ECMA中的字符串值262。我认为你引用的作者批评UTF-16而不是JavaScript的UTF-16一致性。这就是字符串在C#和Java中的工作方式。 - McDowell