javascript – 如何使浏览器中的toLowerCase()和toUpperCase()保持一致
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了javascript – 如何使浏览器中的toLowerCase()和toUpperCase()保持一致,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7995字,纯文字阅读大概需要12分钟。
内容图文
![javascript – 如何使浏览器中的toLowerCase()和toUpperCase()保持一致](/upload/InfoBanner/zyjiaocheng/697/aa5ece9cbdc74bcc8e5c55252a6cb355.jpg)
是否存在String.toLowerCase()和String.toUpperCase()的JavaScript polyfill实现,或者JavaScript中可以使用Unicode字符并且跨浏览器一致的其他方法?
背景信息
执行以下操作会在浏览器中或甚至浏览器版本之间产生不同的结果(例如,FireFox 54与55):
document.write(String.fromCodePoint(223).normalize("NFKC").toLowerCase().toUpperCase().toLowerCase())
在Firefox 55中它为你提供了ss,在Firefox 54中它为你提供了ß.
通常这很好,Locales等机制可以处理你想要的很多情况;但是,当您需要跨平台的一致行为时,例如与google-cloud-firestore等BaaS系统交谈,它可以极大地简化您实际处理客户端内部数据的交互.
解决方法:
请注意,此问题似乎只会影响过时的Firefox版本,因此除非您明确需要支持这些旧版本,否则您可以选择不打扰.您的示例的行为在所有现代浏览器中都是相同的(因为Firefox中的更改).这可以验证using jsvu + eshost:
$jsvu # Update installed JavaScript engine binaries to the latest version.
$eshost -e '"\xDF".normalize("NFKC").toLowerCase().toUpperCase().toLowerCase()'
#### Chakra
ss
#### V8 --harmony
ss
#### JavaScriptCore
ss
#### V8
ss
#### SpiderMonkey
ss
#### xs
ss
但你问如何解决这个问题,让我们继续.
https://tc39.github.io/ecma262/#sec-string.prototype.tolowercase的第4步规定:
Let
cuList
be a List where the elements are the result oftoLowercase(cpList)
, according to the Unicode Default Case Conversion algorithm.
此Unicode默认大小写转换算法在section 3.13 Default Case Algorithms of the Unicode standard中指定.
The full case mappings for Unicode characters are obtained by using the mappings from 07003 plus the mappings from 07004, excluding any of the latter mappings that would conflict. Any character that does not have a mapping in these files is considered to map to itself.
[…]
The following rules specify the default case conversion operations for Unicode strings. These rules use the full case conversion operations,
Uppercase_Mapping(C)
,Lowercase_Mapping(C)
, andTitlecase_Mapping(C)
, as well as the context-dependent mappings based on the casing context, as specified in Table 3-17.For a string
X
:
- R1
toUppercase(X)
: Map each characterC
inX
toUppercase_Mapping(C)
.- R2
toLowercase(X)
: Map each characterC
inX
toLowercase_Mapping(C)
.
这是SpecialCasing.txt的示例,我的注释在下面添加:
00DF ; 00DF ; 0053 0073; 0053 0053; # LATIN SMALL LETTER SHARP S
<code>; <lower>; <title> ; <upper> ; (<condition_list>;)? # <comment>
该线表示U 00DF(‘ß’)下降至U 00DF(ß),上行表示U 0053 U 0053(SS).
以下是UnicodeData.txt的示例,其中添加了我的注释:
0041 ; LATIN CAPITAL LETTER A; Lu;0;L;;;;;N;;;; 0061 ;
<code>; <name> ; <ignore> ; <lower>; <upper>
该行表示U 0041(‘A’)小写为U 0061(‘a’).它没有明确的大写映射,这意味着它是自身的大写.
这是UnicodeData.txt的另一个例子:
0061 ; LATIN SMALL LETTER A; Ll;0;L;;;;;N;; ;0041; ; 0041
<code>; <name> ; <ignore> ; <lower>; <upper>
该行表示U 0061(‘a’)大写为U 0041(‘A’).它没有明确的小写映射,这意味着它会降低自身的范围.
您可以编写一个解析这两个文件的脚本,按照这些示例读取每一行,并构建小写/大写映射.然后,您可以将这些映射转换为一个小型JavaScript库,该库提供符合规范的toLowerCase / toUpperCase功能.
这似乎很多工作.根据Firefox中的旧行为以及究竟改变了什么(?),您可能会将工作限制为SpecialCasing.txt中的特殊映射.(我假设只有特殊的外壳在Firefox 55中发生了变化,基于您的示例提供.)
// Instead of…
function normalize(string) {
const normalized = string.normalize('NFKC');
const lowercased = normalized.toLowerCase();
return lowercased;
}
// …one could do something like:
function lowerCaseSpecialCases(string) {
// TODO: replace all SpecialCasing.txt characters with their lowercase
// mapping.
return string.replace(/TODO/g, fn);
}
function normalize(string) {
const normalized = string.normalize('NFKC');
const fixed = lowerCaseSpecialCases(normalized); // Workaround for old Firefox 54 behavior.
const lowercased = fixed.toLowerCase();
return lowercased;
}
我编写了一个脚本来解析SpecialCasing.txt并生成一个JS库,该库实现了上面提到的lowerCaseSpecialCases功能(如toLower)以及toUpper.这是:https://gist.github.com/mathiasbynens/a37e3f3138069729aa434ea90eea4a3c根据您的确切用例,您可能根本不需要toUpper及其相应的正则表达式和映射.这是完整生成的库:
const reToLower = /[\u0130\u1F88-\u1F8F\u1F98-\u1F9F\u1FA8-\u1FAF\u1FBC\u1FCC\u1FFC]/g;
const toLowerMap = new Map([
['\u0130', 'i\u0307'],
['\u1F88', '\u1F80'],
['\u1F89', '\u1F81'],
['\u1F8A', '\u1F82'],
['\u1F8B', '\u1F83'],
['\u1F8C', '\u1F84'],
['\u1F8D', '\u1F85'],
['\u1F8E', '\u1F86'],
['\u1F8F', '\u1F87'],
['\u1F98', '\u1F90'],
['\u1F99', '\u1F91'],
['\u1F9A', '\u1F92'],
['\u1F9B', '\u1F93'],
['\u1F9C', '\u1F94'],
['\u1F9D', '\u1F95'],
['\u1F9E', '\u1F96'],
['\u1F9F', '\u1F97'],
['\u1FA8', '\u1FA0'],
['\u1FA9', '\u1FA1'],
['\u1FAA', '\u1FA2'],
['\u1FAB', '\u1FA3'],
['\u1FAC', '\u1FA4'],
['\u1FAD', '\u1FA5'],
['\u1FAE', '\u1FA6'],
['\u1FAF', '\u1FA7'],
['\u1FBC', '\u1FB3'],
['\u1FCC', '\u1FC3'],
['\u1FFC', '\u1FF3']
]);
const toLower = (string) => string.replace(reToLower, (match) => toLowerMap.get(match));
const reToUpper = /[\xDF\u0149\u01F0\u0390\u03B0\u0587\u1E96-\u1E9A\u1F50\u1F52\u1F54\u1F56\u1F80-\u1FAF\u1FB2-\u1FB4\u1FB6\u1FB7\u1FBC\u1FC2-\u1FC4\u1FC6\u1FC7\u1FCC\u1FD2\u1FD3\u1FD6\u1FD7\u1FE2-\u1FE4\u1FE6\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u1FFC\uFB00-\uFB06\uFB13-\uFB17]/g;
const toUpperMap = new Map([
['\xDF', 'SS'],
['\uFB00', 'FF'],
['\uFB01', 'FI'],
['\uFB02', 'FL'],
['\uFB03', 'FFI'],
['\uFB04', 'FFL'],
['\uFB05', 'ST'],
['\uFB06', 'ST'],
['\u0587', '\u0535\u0552'],
['\uFB13', '\u0544\u0546'],
['\uFB14', '\u0544\u0535'],
['\uFB15', '\u0544\u053B'],
['\uFB16', '\u054E\u0546'],
['\uFB17', '\u0544\u053D'],
['\u0149', '\u02BCN'],
['\u0390', '\u0399\u0308\u0301'],
['\u03B0', '\u03A5\u0308\u0301'],
['\u01F0', 'J\u030C'],
['\u1E96', 'H\u0331'],
['\u1E97', 'T\u0308'],
['\u1E98', 'W\u030A'],
['\u1E99', 'Y\u030A'],
['\u1E9A', 'A\u02BE'],
['\u1F50', '\u03A5\u0313'],
['\u1F52', '\u03A5\u0313\u0300'],
['\u1F54', '\u03A5\u0313\u0301'],
['\u1F56', '\u03A5\u0313\u0342'],
['\u1FB6', '\u0391\u0342'],
['\u1FC6', '\u0397\u0342'],
['\u1FD2', '\u0399\u0308\u0300'],
['\u1FD3', '\u0399\u0308\u0301'],
['\u1FD6', '\u0399\u0342'],
['\u1FD7', '\u0399\u0308\u0342'],
['\u1FE2', '\u03A5\u0308\u0300'],
['\u1FE3', '\u03A5\u0308\u0301'],
['\u1FE4', '\u03A1\u0313'],
['\u1FE6', '\u03A5\u0342'],
['\u1FE7', '\u03A5\u0308\u0342'],
['\u1FF6', '\u03A9\u0342'],
['\u1F80', '\u1F08\u0399'],
['\u1F81', '\u1F09\u0399'],
['\u1F82', '\u1F0A\u0399'],
['\u1F83', '\u1F0B\u0399'],
['\u1F84', '\u1F0C\u0399'],
['\u1F85', '\u1F0D\u0399'],
['\u1F86', '\u1F0E\u0399'],
['\u1F87', '\u1F0F\u0399'],
['\u1F88', '\u1F08\u0399'],
['\u1F89', '\u1F09\u0399'],
['\u1F8A', '\u1F0A\u0399'],
['\u1F8B', '\u1F0B\u0399'],
['\u1F8C', '\u1F0C\u0399'],
['\u1F8D', '\u1F0D\u0399'],
['\u1F8E', '\u1F0E\u0399'],
['\u1F8F', '\u1F0F\u0399'],
['\u1F90', '\u1F28\u0399'],
['\u1F91', '\u1F29\u0399'],
['\u1F92', '\u1F2A\u0399'],
['\u1F93', '\u1F2B\u0399'],
['\u1F94', '\u1F2C\u0399'],
['\u1F95', '\u1F2D\u0399'],
['\u1F96', '\u1F2E\u0399'],
['\u1F97', '\u1F2F\u0399'],
['\u1F98', '\u1F28\u0399'],
['\u1F99', '\u1F29\u0399'],
['\u1F9A', '\u1F2A\u0399'],
['\u1F9B', '\u1F2B\u0399'],
['\u1F9C', '\u1F2C\u0399'],
['\u1F9D', '\u1F2D\u0399'],
['\u1F9E', '\u1F2E\u0399'],
['\u1F9F', '\u1F2F\u0399'],
['\u1FA0', '\u1F68\u0399'],
['\u1FA1', '\u1F69\u0399'],
['\u1FA2', '\u1F6A\u0399'],
['\u1FA3', '\u1F6B\u0399'],
['\u1FA4', '\u1F6C\u0399'],
['\u1FA5', '\u1F6D\u0399'],
['\u1FA6', '\u1F6E\u0399'],
['\u1FA7', '\u1F6F\u0399'],
['\u1FA8', '\u1F68\u0399'],
['\u1FA9', '\u1F69\u0399'],
['\u1FAA', '\u1F6A\u0399'],
['\u1FAB', '\u1F6B\u0399'],
['\u1FAC', '\u1F6C\u0399'],
['\u1FAD', '\u1F6D\u0399'],
['\u1FAE', '\u1F6E\u0399'],
['\u1FAF', '\u1F6F\u0399'],
['\u1FB3', '\u0391\u0399'],
['\u1FBC', '\u0391\u0399'],
['\u1FC3', '\u0397\u0399'],
['\u1FCC', '\u0397\u0399'],
['\u1FF3', '\u03A9\u0399'],
['\u1FFC', '\u03A9\u0399'],
['\u1FB2', '\u1FBA\u0399'],
['\u1FB4', '\u0386\u0399'],
['\u1FC2', '\u1FCA\u0399'],
['\u1FC4', '\u0389\u0399'],
['\u1FF2', '\u1FFA\u0399'],
['\u1FF4', '\u038F\u0399'],
['\u1FB7', '\u0391\u0342\u0399'],
['\u1FC7', '\u0397\u0342\u0399'],
['\u1FF7', '\u03A9\u0342\u0399']
]);
const toUpper = (string) => string.replace(reToUpper, (match) => toUpperMap.get(match));
内容总结
以上是互联网集市为您收集整理的javascript – 如何使浏览器中的toLowerCase()和toUpperCase()保持一致全部内容,希望文章能够帮你解决javascript – 如何使浏览器中的toLowerCase()和toUpperCase()保持一致所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。