我试图理解表情符号是如何工作的,另一件事是我的浏览器中的任何textarea如何处理一个看似2个表示为一个的字符?
例如:
"".length
// -> 2
答案 0 :(得分:10)
Javascript使用UTF-16(source)来管理字符串。
在UTF-16中,有1,112,064个可能的字符。现在,每个角色都使用code points来表示(*)。在UTF-16中,一个代码点使用两个字节(16位)来保存。这意味着使用一个代码点,您只能 65536个不同的字符。
这意味着一些字符必须用两个代码点表示。
String.length()返回字符串中的代码单元数,而不是字符数。
MDN很好地解释了关于String.length()
的页面上的内容此属性返回字符串中的代码单元数。 UTF-16是JavaScript使用的字符串格式,它使用单个16位代码单元来表示最常见的字符,但需要使用两个代码单元来表示不太常用的字符,因此有可能将长度返回的值返回到与字符串中的实际字符数不匹配。
(*):实际上, 010000 - 03FFFF 和 040000 - 10FFFF 范围内的一些字符每个代码点最多可使用4个字节(32位),但这不会改变答案:一些字符需要表示超过2个字节,因此它们需要多于1个代码点。
这意味着一些需要16位以上的字符长度为1。与 0x03FFFF 一样,它需要21位,但它只使用UTF-16中的一个代码单元,因此其String.length为1。
console.log(String.fromCharCode(0x03FFFF).length)
答案 1 :(得分:7)
我相信rpadovani回答了你的问题"为什么"问题最好,但是对于能够在这种情况下获得正确的字形数的实现,Lodash已经在他们的toArray模块中解决了这个问题。
例如,
_.toArray('12').length; // --> 3
或者,如果你想从字符串中敲掉几个任意字符,你就可以操作并重新加入数组,如:
_.toArray("trimToEightGlyphs").splice(0,8).join(''); // --> 'trimToE'
答案 2 :(得分:1)
我找到了一种获得正确结果的简单方法。
这是:
'?Some text with emojis?'.match(/./gu)
它应该返回:
[ "?","S", "o", "m", "e", " ", "t", "e", "x", "t", " ", "w", "i", "t", "h", " ", "e", "m", "o", "j", "i", "s", "?"]
然后可以在其上应用.length
:
'?'.match(/./gu).length == 1
它使用正则表达式匹配:/./gu
.
匹配任何单个字符。
g
的意思是'global':基本上,它允许在第一局比赛后不停止。
u
的意思是“ unicode”:它允许以正确的方式显示字符(没有?
的情况下将显示为��
(所以是2个字符))
您可以添加m以支持多行(/./gum
)
希望如此?