为什么表情符号字符串长度为2?

时间:2016-07-13 07:36:14

标签: javascript utf-8 emoji

我试图理解表情符号是如何工作的,另一件事是我的浏览器中的任何textarea如何处理一个看似2个表示为一个的字符?

例如:

"".length
// -> 2

此处有更多示例: https://jsbin.com/zazexenigi/edit?js,console

3 个答案:

答案 0 :(得分:10)

Javascript使用UTF-16source)来管理字符串。

在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

希望如此?