/^.{2,8}$/u.test('😀😀')
/^\p{Extended_Pictographic}$/u.test('😀')
node -e "console.log([...'😀😀'].length)"

昵称校验写 /^.{2,8}$/,输入四个 emoji 通过校验,输入一个 emoji 加两个汉字却被判超长,浏览器和 Node 结果一致。这类现象通常不是突然出现的,往前翻半天日志能看到苗头。

追下去是这么回事:没有 u 标志时正则按 UTF-16 码元匹配,一个 emoji 算两个字符,量词数的是码元不是肉眼看到的字。加了 u 之后点号才按码点走。

「正则 u 标志」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。监控和日志的时间要对上,时区不一致会多绕很大一圈。

临时改动用注释写上日期和原因,过两周自己都记不清为什么这么写。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。

一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。

处理上按这个顺序:校验正则统一加 u 标志;长度用 Array.from 或 Intl.Segmenter 计算;需要匹配组合 emoji 时用 \p{Extended_Pictographic};把正则写进单测 覆盖 emoji 和生僻字。

确认没问题再收工,四个 emoji 判为 4 个字符 校验结果和界面显示的字数一致。

作者 9823189