首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么JavaScript `Intl.Collator.prototype.compare()方法对特殊字符的比较结果与传统的UTF-16方法不同?

为什么JavaScript `Intl.Collator.prototype.compare()方法对特殊字符的比较结果与传统的UTF-16方法不同?
EN

Stack Overflow用户
提问于 2021-10-01 12:19:16
回答 1查看 578关注 0票数 3

今天,我偶然发现了JavaScript / ECMAScript国际化API中一个奇怪的问题,我在任何地方都找不到合适的解释。在比较两个特定字符-正斜杠(/)和下划线(_)字符时,我得到了不同的结果:

  1. 普通香草/传统UTF-16的比较
  2. Intl.Collator.prototype.compare()方法

基于平原/传统UTF-16的比较

代码语言:javascript
复制
// Vanilla JavaScript comparator
const cmp = (a, b) => a < b ? -1 : a > b ? 1 : 0;

console.log(cmp('/', '_'));
// Output: -1

// When sorting
const result = ['/', '_'].sort(cmp);

console.log(result);
// Output: ['/', '_']

Intl.Collator.prototype.compare()方法

代码语言:javascript
复制
const collator = new Intl.Collator('en', {
  sensitivity: 'base',
  numeric: true
});

console.log(collator.compare('/', '_'));
// Output: 1

// When sorting
const result = ['/', '_'].sort(collator.compare);

console.log(result);
// Output: ['_', '/']

问题

为什么这两种技术产生不同的结果?这是ECMAScript实现中的一个bug吗?我在这里漏掉了什么?是否还有其他这样的字符组合会对英语(en)语言/地区产生不同的结果?

编辑2021-10-01

正如@t crowder所指出的,将所有"ASCII“替换为"UTF-16”。

EN

回答 1

Stack Overflow用户

发布于 2021-10-01 12:31:49

总体而言

当您在字符串上使用<>时,会根据它们的UTF-16代码单元值进行比较(不是ASCII,但是ASCII与许多常见字符的值重叠)。温和地说,这是有问题的。例如,问问法语中的"z" < "é"是否真的应该是真的(表示zé之前):

代码语言:javascript
复制
console.log("z" < "é"); // true?!?!

当您使用Intl.Collator.prototype.compare时,它会根据您提供的选项为您的地区使用适当的排序规则(松散地排序)。在许多情况下,这可能是与UTF-16代码单元值的结果不同的。例如,即使在en区域设置中,Collator也返回zé之后出现的更合理的结果

代码语言:javascript
复制
console.log(new Intl.Collator("en").compare("z", "é")); // 1

_/

我无法具体地告诉您,为什么_/与您使用的UTF-16代码单元有不同的顺序(以及我正在使用的代码单元),无论是en-USen-UK还是其他什么。但是,发现ASCII和Unicode之间的顺序不同并不令人惊讶。(请记住,_/的UTF-16代码单元值来自于它们的ASCII值。)

ASCII的顺序是在20世纪60年代初精心设计的(有关于它的精彩细节的PDF ),但除了A和0-9的排序之外,基本上不涉及语言排序。/从1963年起就在最初的ASCII中。直到1967年,_才被添加到一个比/更高的可用位置。在ASCII中,可能没有比这更重要的原因了,为什么_/晚/高(数字)。

Unicode的排序顺序是在1990年代(一直到今天)仔细设计的,有不同的目标(包括语言目标)、设计要求和设计约束。据我所知(我不是Unicode专家),TR10TR35的第5部分描述了Unicode的排序规则。我还没有找到_在根排序规则中位于/之前的具体理由(en使用根排序规则)。我肯定它就在里面。我确实注意到,它的一个方面似乎是按类别分组。_的类别是"Connector标点符号“,而/的类别是”其他标点符号“。也许这与/_晚的原因有关。

但基本答案是:它们不同,因为ASCII的排序和Unicode排序是根据不同的约束和需求设计的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69405786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档