js 将字符串分割成数组时emoji表情被分割成了乱码的解决办法
直接看图吧
直接使用索引:
使用split:
使用charAt:
解决办法
// 文本分割
const splitGraphemes = (input) => {
if (typeof Intl !== 'undefined' && Intl.Segmenter) {
const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
return Array.from(segmenter.segment(input), (segment) => segment.segment);
} else {
// 回退到正则分割
const graphemeRegex = /(?:\p{Extended_Pictographic}(?:\p{Emoji_Modifier}|\u200D\p{Extended_Pictographic})*|[\s\S])/gu;
return [...input.matchAll(graphemeRegex)].map(match => match[0]);
}
}
解释
Intl.Segmenter
是一个国际化 API,用于根据语言环境和特定的粒度分割字符串。
- 这里判断当前环境是否支持
Intl.Segmenter
:- 如果支持,创建一个
Segmenter
实例:const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });
'en'
:指定语言环境为英文(但由于grapheme
是独立于语言的,因此适用于多种语言)。{ granularity: 'grapheme' }
:指定粒度为字素(grapheme
),即按人类可见的字符进行分割。- 然后通过
Array.from
遍历segmenter.segment(input)
返回的迭代器,将每个segment
对象的segment
属性提取到数组中。
- 如果支持,创建一个
如果 Intl.Segmenter
不可用,则使用正则表达式进行分割:
const graphemeRegex = /(?:\p{Extended_Pictographic}(?:\p{Emoji_Modifier}|\u200D\p{Extended_Pictographic})*|[\s\S])/gu;
return [...input.matchAll(graphemeRegex)].map(match => match[0]);
\p{Extended_Pictographic}
:匹配扩展图形字符(主要是表情符号和特殊符号)。(?:...)
:非捕获组,用于将匹配的表情符号与修饰符或零宽连接符(u200D
)组合起来。[\s\S]
:匹配所有其他字符(如果不是表情符号)。/gu
:g
:全局匹配,匹配所有字素。u
:启用 Unicode 模式,确保正确处理 Unicode 字符。
步骤:
- 使用
input.matchAll(graphemeRegex)
获取所有匹配的字素。 - 将每个匹配的结果提取为一个字符串并返回为数组。
Intl.Segmenter
是更现代、准确的方式,尤其适用于需要国际化支持的环境。- 如果
Intl.Segmenter
不可用,则使用正则表达式作为兼容方案。
适用场景:
- 处理用户输入中的 Emoji 或复合字符。
- 文本编辑器、聊天应用等需要逐字素处理的应用。