我在现有的关于星体层代码点或国际化问题的答案中没有看到任何提及。“大写字母”在使用给定脚本的每种语言中的含义并不相同。_起初,我没有看到任何解决星体层代码点相关问题的答案。有一个(https://stackoverflow.com/a/45224904/1631952),但它有点埋了(我想这一个会是这样的!)_---大多数建议的功能如下所示:函数大写首字母(str){return str[0].toUpperCase()+str.slice(1);}然而,一些大小写字符不在BMP(基本多语言平面,代码点U+0到U+FFFF)范围内。例如,以沙漠文本为例:大写首字母(“𐐶𐐲𐑌𐐼𐐲𐑉"); // "𐐶𐐲𐑌𐐼𐐲𐑉"这里的第一个字符无法大写,因为字符串的数组索引属性不访问字符或代码点。他们访问UTF-16代码单元。切片时也是如此,索引值指向代码单元。碰巧UTF-16代码单元与两个范围内的代码点的代码点是1:1,即U+0到U+D7FF和U+E000到U+FFFF。大多数大小写字符都属于这两个范围,但不是全部。从ES2015开始,处理这个问题变得更容易了`String.prototype[@@iterator]`生成与代码点\*对应的字符串。例如,我们可以这样做:函数大写FirstLetter([first,…rest]){return[first.toUpperCase(),…rest].join('');}大写首字母(“𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"对于较长的字符串,这可能不是非常有效的\*\*-我们实际上不需要迭代余数。我们可以使用`String.prototype.codePointAt`来获得第一个(可能的)字母,但我们仍然需要确定切片应该从哪里开始。避免迭代余数的一种方法是测试第一个码点是否在BMP之外;如果不是,切片从1开始,如果是,切片从2开始。函数大写首字母(str){const firstCP=str.codePointAt(0);常量索引=第一个CP>0xFFFF?2 : 1;return String.fromCodePoint(firstCP).toUpperCase()+str.slice(index);}大写首字母(“𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"如果必要的话,我们还可以在ES5及以下版本中进一步采用该逻辑来实现这一点。ES5中没有用于处理代码点的内部方法,因此我们必须手动测试第一个代码单元是否是代理:函数大写首字母(str){var firstCodeUnit=字符串[0];if(firstCodeUnit<'\uD800'||firstCode Unit>'\uDFFF'){return str[0].toUpperCase()+str.slice(1);}return str.slice(0,2).toUpperCase()+str.slices(2);}大写首字母(“𐐶𐐲𐑌𐐼𐐲𐑉") // "𐐎𐐲𐑌𐐼𐐲𐑉"一开始我还提到了国际化的考虑。其中一些很难解释,因为它们不仅需要了解所使用的语言,还可能需要了解该语言中单词的特定知识。例如,爱尔兰有向字“mb”在单词的开头大写为“mb”,而德语eszett从不开始单词(afaik),这意味着在德语中从“SS”小写需要额外的知识(它可以是“SS”,也可以是“ß”,具体取决于单词)。这个问题最著名的例子可能是土耳其语。在土耳其语拉丁语中,i的大写形式是is,而i的小写形式是In——它们是两个不同的字母。幸运的是,我们确实有办法解释这一点:函数大写FirstLetter([first,…rest],locale){return[first.toLocaleUpperCase(locale),…rest].join('');}大写首字母(“italya”,“en”)//“italya”大写首字母(“italya”,“tr”)//“伊塔利亚”在浏览器中,用户最喜欢的语言标签由“navigator.language”表示,在“navigator.languages”中可以找到按偏好顺序排列的列表,并且可以使用“Object(element.colosest('[lang]')).lang||YOUR_DEFAULT_HERE”获得给定DOM元素的语言。---问这个问题的人很可能与Deseret资本化或国际化无关。但意识到这些问题是件好事,因为即使目前还不担心,你最终也很有可能遇到它们。它们不是“边缘”案例,或者更确切地说,它们不是按定义的边缘案例——总之,在整个国家,大多数人都说土耳其语,将代码单元与代码点混为一谈是一个相当常见的错误来源(尤其是关于表情符号)。字符串和语言都很复杂!---_\*或代理代码单元(如果是孤立的)__\*\*也许吧。我还没有测试过它。除非你确定资本化是一个有意义的瓶颈,否则我可能不会费劲——选择你认为最清晰易读的内容__\*\*\*这样的函数可能希望测试第一个和第二个代码单元,而不仅仅是第一个,因为第一个单元可能是孤立的代理。例如,输入“\uD800x”将X as-is大写,这可能是预期的,也可能不是预期的_