You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何'❌'[0]==='❌'成立但'✔️'[0]==='✔️'不成立?Unicode相关问题

底层运行逻辑

JavaScript字符串采用UTF-16编码存储,所有默认的字符串操作(包括下标取值、split('')拆分)都是按16位的UTF-16码元处理,而非用户视觉上感知的单个「字符」(Unicode字素簇)。
两个符号的编码差异直接导致了操作结果不同:

  • ❌ 对应单个Unicode码点U+274C,仅占1个UTF-16码元,因此'❌'[0]可以取到完整的符号,比较返回true。
  • ✔️ 是由两个码点组合而成的字素簇:基础符号为✔(U+2714,默认渲染为黑白文本样式),后接变体选择符U+FE0F,作用是指定该符号渲染为彩色emoji样式。整个✔️占2个UTF-16码元,因此'✔️'[0]只能取到前半部分的基础符号✔,和完整的✔️比较返回false,和单独的✔比较返回true。

你遇到的统计结果异常也源于此:split('')会把'✔️❌✔️❌'按码元拆分为['✔', '️', '❌', '✔', '️', '❌'],数组中不存在完整的✔️元素,因此统计长度为0,而❌是单个码元,拆分后正常存在,统计结果为2。

正确处理方案

如果要按视觉字符做比较、统计操作,需要使用支持Unicode字素簇处理的API:

  1. 字符统计推荐使用内置的Intl.Segmenter接口,专门用于按视觉字素簇拆分字符串:
// 初始化字素簇分割器
const segmenter = new Intl.Segmenter('zh', { granularity: 'grapheme' });
// 拆分得到视觉字符数组
const charList = Array.from(segmenter.segment('✔️❌✔️❌'), item => item.segment);

console.log(charList.filter(e => e === '❌').length) // 输出2
console.log(charList.filter(e => e === '✔️').length) // 输出2
  1. 单独比较两个视觉字符是否相等时,可以先调用normalize()方法做Unicode规范化后再比较:
'✔️'.normalize() === '✔️'.normalize() // 输出true

内容的提问来源于stack exchange,提问作者Wilhelm Olejnik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 03:39:01