具体来说,JS引擎对小写和大写区域设置敏感

In what JS engines, specifically, are toLowerCase & toUpperCase locale-sensitive?

本文关键字:区域 设置 具体来说 JS 引擎      更新时间:2024-07-05

在某些库的代码中(例如 AngularJS,链接指向代码中的特定行(,我可以看到使用了自定义大小写转换函数而不是标准函数。假设在具有土耳其语区域设置的浏览器中,标准函数无法按预期工作,这是合理的:

console.log("SCRIPT".toLowerCase()); // "scrıpt"
console.log("script".toUpperCase()); // "SCRİPT"

但事实真的如此吗?浏览器真的是这样行为的吗?如果是这样,他们中的哪一个会这样做?节点.js呢?其他 JS 引擎?

toLocaleLowerCasetoLocaleUpperCase 方法的存在意味着toLowerCasetoUpperCase是区域设置不变的,不是吗?

具体而言,对于哪些浏览器,Angular 团队在代码中保留了此检查:if ('i' !== 'I'.toLowerCase())...


如果您的浏览器(设备(使用土耳其语或阿塞拜疆语言环境,请运行此代码段,如果您发现问题确实存在,请写信给我。

if ('i' !== 'I'.toLowerCase()) {
  document.write('Ooops! toLowerCase is locale-sensitive in your browser. ' +
    'Please write your user-agent in the comments to this question: ' +
    navigator.userAgent); 
} else {
  document.write('toLowerCase isn''t locale-sensitive in your browser. ' +
    'Everything works as expected!');
}
<html lang="tr">

注意:请注意,我无法测试它!


根据 ECMAScript 规范:

String.prototype.toLowerCase ( (

[...]

出于此操作的目的,16 位代码单元的 字符串在 Unicode 基本多语言中被视为代码点 飞机。代理项码位直接从 S 传输到 L 没有任何映射。

必须根据 Unicode 字符数据库(这明确不仅包括 UnicodeData.txt 文件,也是 SpecialCasings.txt 文件 在 Unicode 2.1.8 及更高版本中随附(。

[...]

String.prototype.toLocaleLowerCase ( (

此函数的工作方式与 toLowerWrite 完全相同,除了它的 结果旨在为主机生成正确的结果 环境的当前区域设置,而不是与区域设置无关的结果。 只有在少数情况下才会有差异(例如土耳其语( 该语言的规则与常规 Unicode 冲突 案例映射。

[...]

根据 Unicode 字符数据库特殊大小写:

[...]

格式

此文件中的条目采用以下机器可读格式:

<code>; <lower>; <title>; <upper>; (<condition_list>;)? # <comment>

无条件映射

[...]

保留 I 与点的规范等价性。突厥语被处理 下面。

0130; 0069 0307; 0130; 0130; # LATIN CAPITAL LETTER I WITH DOT ABOVE

[...]

语言敏感映射 这些字符的完整大小写映射取决于语言,也许还取决于语言 上下文(哪些字符在之前或之后(。欲了解更多信息 请参阅此文件的标头和 Unicode 标准。

立陶宛语

立陶宛语在后跟重音符号时以小写 i 保留点。

删除带有大写或标题大小写的"i"后面的点

0307; 0307; ; ; lt After_Soft_Dotted; # COMBINING DOT ABOVE

在小写字母 I 和 J 时在上面引入一个明确的点 每当上面有更多的口音时。 (立陶宛语中使用的重音:grave,asharp,上面的波浪号和ogonek(

0049; 0069 0307; 0049; 0049; lt More_Above; # LATIN CAPITAL LETTER I

004A; 006A 0307; 004A; 004A; lt More_Above; # LATIN CAPITAL LETTER J

012E; 012F 0307; 012E; 012E; lt More_Above; # LATIN CAPITAL LETTER I WITH OGONEK

00CC; 0069 0307 0300; 00CC; 00CC; lt; # LATIN CAPITAL LETTER I WITH GRAVE

00CD; 0069 0307 0301; 00CD; 00CD; lt; # LATIN CAPITAL LETTER I WITH ACUTE

0128; 0069 0307 0303; 0128; 0128; lt; #LATIN CAPITAL LETTER I WITH TILDE

土耳其语和阿塞拜疆语

我和我点;I-dot 和 i 是土耳其语和阿塞拜疆语中的案例对 以下规则处理这些情况。

0130; 0069; 0130; 0130; tr; # LATIN CAPITAL LETTER I WITH DOT ABOVE

0130; 0069; 0130; 0130; az; # LATIN CAPITAL LETTER I WITH DOT ABOVE

小写时,删除序列 I + dot_above 中的dot_above,这将变成 i。 这与规范等效 I-dot_above 的行为相匹配

0307; ; 0307; 0307; tr After_I; # COMBINING DOT ABOVE

0307; ; 0307; 0307; az After_I; # COMBINING DOT ABOVE

小写时,除非 I 在dot_above之前,否则它会变成无点 i。

0049; 0131; 0049; 0049; tr Not_Before_Dot; # LATIN CAPITAL LETTER I

0049; 0131; 0049; 0049; az Not_Before_Dot; # LATIN CAPITAL LETTER I

大写时,i 变成虚线大写 I

0069; 0069; 0130; 0130; tr; # LATIN SMALL LETTER I

0069; 0069; 0130; 0130; az; # LATIN SMALL LETTER I

注意:以下情况已在 UnicodeData.txt 文件中。

0131; 0131; 0049; 0049; tr; # LATIN SMALL LETTER DOTLESS I

EOF

另外,根据JavaScript for Absolute Beginners(由Terry McNavage撰写(:

> "I".toLowerCase() // "i"
> "i".toUpperCase() // "I"
> "I".toLocaleLowerCase() // "<dotless-i>"
> "i".toLocaleUpperCase() // "<dotted-I>"

注意:根据您的操作系统设置toLocaleLowerCase()toLocaleUpperCase()转换大小写。必须将这些设置更改为土耳其语,前面的示例才能正常工作。或者只是相信我的话!

根据 bobince 对将 JavaScript 字符串转换为全部小写的评论? 问题:

Accept-Languagenavigator.language是两个完全独立的 设置。 Accept-Language反映了用户选择的偏好 他们希望在网页中接收哪些语言(此设置是 不幸的是,JS无法访问(。 navigator.language只是反映 安装了 Web 浏览器的哪个本地化版本,并且应该 一般不用于任何东西。这两个值都不相关 到系统区域设置,这是决定什么的位 toLocaleLowerCase(( 就可以了;这是超出范围的操作系统级别设置 浏览器的首选项。


因此,将lang="tr-TR"设置为 html 不会反映真实的测试用例,因为它是重现特殊大小写示例所需的操作系统设置。

我认为在使用 toLowerCase()toUpperCase() 时,只有小写的点 I 或大写无点 i 是特定于语言环境的。

根据那些可靠/官方消息来源,我认为你是对的:'i' !== 'I'.toLowerCase()总是会评估为错误。

但是,正如我所说,我无法在这里测试它。

任何遵循 ECMA-262 5.1 标准的 JS 实现都必须实现 String.prototype.toLocaleLowerCaseString.prototype.toLocaleUpperCase

根据标准toLocaleLowerCase应该根据特定于区域设置的映射将字符串转换为小写映射。

其中 as toLowerCase转换为由 unicode 映射定义的小写字符串。

对于大多数语言,toLocaleLowerCasetoLowerCase给出相同的结果。但是对于某些语言,如土耳其语,大小写映射不遵循 unicode 映射,因此toLowerCasetoLocaleLowerCase给出不同的结果。

您使用的库/框架(Jquery,Angular,Node其他任何(没有任何区别。它是你用来运行你的JS库的JS实现,它使事情发生和改变。

出于所有实际目的,可以准确地得出结论,Node/Angular 或任何其他 JS 库和框架在处理字符串时的行为都完全相同(只要它们被实现 ECMA-262 3 及更高版本的 JS 引擎使用(。话虽如此,我相信许多框架扩展了字符串对象以添加更多功能,但 ECMA-262 5.1 定义的基本属性和函数始终存在,并且行为完全相同。

了解更多 : http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4.17

就浏览器而言

,所有现代浏览器都在其JS引擎中实现了ECMA-262 5.1标准。我不确定 Node,但从我对 Node 的有限曝光来看,我认为他们也使用根据 ECMA-262 5.1 标准实现的 JS。