对于含有emoji的字符串,Javascript是不能直接完成正确的随机访问的。比如对`s = '😀😃😄😁🙂'来说,我可以看到下面的结果
> s.length
10
> s[1]
'\uDE00'
> "\u{1F600}".length
2
也就是说,对于含有emoji的字符串,直接通过默认的字符串操作机制来访问可能会导致一些问题。为了避免出现这些问题,我们可以考虑采用一些方法先把字符串转换成一个Array,Array的每个元素都是一个unicode。
方法1 使用unicode regex
可以通过unicode的正则表达式的matchAll方法来把字符串按照unicode字符来切割成一个array对象。方法就是使用/./ug 这个正则表达式直接来matchAll
> s.matchAll(/./ug).toArray().map(x => x[0])
(5) ['😀', '😃', '😄', '😁', '🙂']
对于存在换行符的字符串,需要使用/./ugs 这个正则表达式
> s = '😀😃😄😁🙂\n😀😃😄😁🙂\n😀😃😄😁🙂'
> s.matchAll(/./ugs).toArray().map(x => x[0])
(17) ['😀', '😃', '😄', '😁', '🙂', '\n', '😀', '😃', '😄', '😁', '🙂', '\n', '😀', '😃', '😄', '😁', '🙂']
这样就可以针对得到的array对象进行操作,之后再用.join('') 方法可以恢复为一个字符串。
方法2 使用Intl.segmenter
第二种方法是使用Intl.segmenter来切分字符串,方法如下
> let segmenter = new Intl.Segmenter();
> [...segmenter.segment(s)].map(x => x.segment)
(5) ['😀', '😃', '😄', '😁', '🙂']
这样也就可以继续对得到的array进行操作了。
以上是在javascript中应对emoji等特殊的unicode的方法。