在JS引擎中,具体来说,是针对低容量的& toUpperCase语言环境敏感?

时间:2015-03-01 09:36:00

标签: javascript angularjs unicode internationalization turkish

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

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

但这是真的还是一直如此?浏览器真的有这样的表现吗?如果是这样,他们中的哪一个呢? node.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">

2 个答案:

答案 0 :(得分:14)

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

根据标准toLocaleLowerCase,根据特定于语言环境的映射,将字符串转换为它的小写映射。

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

对于大多数语言toLocaleLowerCasetoLowerCase都会给出相同的结果。但对于某些语言,例如土耳其语,案例映射不会遵循unicode映射,因此toLowerCasetoLocaleLowerCase会产生不同的结果。

您使用的库/框架(Jquery,Angular,Node,无论如何)都没有任何区别。它是用于运行JS库的JS实现来实现和改变的。

出于所有实际目的,可以准确地得出结论,Node / Angular或任何其他JS库和框架在处理字符串时的行为完全相同(只要它们被JS Engine用于实现ECMA-262) 3以上)。话虽如此,我确信很多框架都会扩展字符串对象以添加更多功能,但basic properties and functions defined by ECMA-262 5.1始终存在并且WILL的行为完全相同。

要了解详情: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。

答案 1 :(得分:13)

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


根据ECMAScript specification

  

String.prototype.toLowerCase()

     

[...]

     

出于此操作的目的,16位代码单元   字符串被视为Unicode Basic Multilingual中的代码点   飞机。代理代码点直接从S转移到L.   没有任何映射。

     

结果必须根据中的案例映射派生   Unicode字符数据库 (这显然不仅包括   UnicodeData.txt文件, 以及SpecialCasings.txt 文件   在Unicode 2.1.8及更高版本中随附。

     

[...]

     

String.prototype.toLocaleLowerCase()

     

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

     

[...]

根据Unicode Character Database Special Casing

  

[...]

     

格式

     
    

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

         

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

  
     

无条件映射

     

[...]

     
    

保留带点的I的规范等价。突厥语被处理     下方。

  
     

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

     

[...]

     
    

语言敏感映射     这些是完整案例映射依赖于语言的字符,也许也是     上下文(字符在之前或之后)。欲获得更多信息     请参阅此文件的标题和Unicode标准。

  
     

立陶宛语

     
    

立陶宛语在点缀后以小写字母i保留点。

         

在“i”之后用上部或标题

删除DOT ABOVE   
     

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

     
    

在降低资本I和J的时候,在上面引入一个明确的点     每当有更多重音时。     (在立陶宛语中使用的口音:严重,尖锐,上面和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和我是土耳其语和阿塞拜疆的案例对     以下规则处理这些情况。

  
     

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

     
    

当小写时,除非我在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

     
    

当大写时,我变成了一个虚线的大写我

  
     

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 (by Terry McNavage)

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

注意toLocaleLowerCase()toLocaleUpperCase()根据您的操作系统设置转换大小写 。您必须将这些设置更改为土耳其语才能使上一个样本生效。或者只是听我的话!

根据bobince's comment over Convert JavaScript String to be all lower case? question

  

Accept-Languagenavigator.language两个完全分开   设置。 Accept-Language反映了用户选择的偏好   他们想要在网页上接收什么语言(这个设置是   难以接受的JS)。 navigator.language仅仅反映了   Web浏览器的本地化安装,应该   通常不用于任何东西。这两个值都是无关的   到系统区域设置,这是决定什么的位   toLocaleLowerCase()会做; 这是操作系统级别设置超出范围   浏览器的首选项。


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

我认为在使用toLowerCase()toUpperCase()时,只有小写字母-I或大写字母dotless-i才是特定于区域设置。

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

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