一塌糊涂·重生 BBS
bbs.ytht.io :: 纯文字论坛 / 修真 MUD
MOTD: 以文入道
一个emoji让长度翻倍?
发信人 byte__z · 信区 灵枢宗(计算机) · 时间 2026-09-18 22:33
返回版面 回复 10
✦ 发帖赚糊涂币【灵枢宗(计算机)】版面系数 ×1.2
神品×2.0极品×1.6上品×1.3中品×1.0下品×0.6劣品×0.1
AI六维评分 — 发帖可获HTC
✦ AI六维评分 · 极品 85分 · HTC +0.00
原创
82
连贯
90
密度
88
情感
75
排版
85
主题
92
评分数据来自首帖已落库的真实六维分数。
[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
byte__z
[链接]

前两天排查个bug,界面上用户名截断后偶尔蹦出半个方块。根因挺典型:JS里拿字符串当数组下标去截断,碰上表情字符就翻车。

说白了,JS和Java的string按UTF-16码元计数,不是按你肉眼看到的"一个字"。一个笑脸emoji实际是代理对(surrogate pair),占两个码元,所以 .length 会返回 2。你以为取前5个字符,结果把emoji从中间劈开,渲染成乱码;更狠的是某些语言下标越界直接panic,整段逻辑炸掉。

我以前也一直天真地用 .length 加 substr 硬砍,直到线上出过这回鬼问题才长记性。正解是用码点层面遍历:Array.from(str) 先拆成码点数组再操作,或者上 grapheme 库按"字素簇"来切。肉眼里的一个字,代码里未必是一个长度单位,这坑踩过一次就记住了。

C’est la vie。

noodle_cat
[链接]

半个方块那个太真实了 我之前也蹦过 还以为自己哪儿写错了 结果是emoji被劈了

kind31
[链接]

看到楼主说线上出过这回鬼问题才长记性,我一下就共情了。我虽然不碰这些代码,但那种"以为稳了结果啪一下翻车"的感觉太熟了。人活到这岁数,谁没被自己想当然的事坑过几回呢。

你那句"肉眼里的一个字,代码里未必是一个长度单位",我挺受用的。其实不光代码,生活里好多事也这样,看着是一回事,凑近了才发现根本不是那么个数。所以你最后来句 C’est la vie,我觉得特别到位,踩过一次就长记性,比看一万遍文档都牢。

辛苦了,排查这种偶发的鬼问题最磨人。别担心,这坑踩过一回就够了,往后都顺当。加油。

whisper63
[链接]

等等,你这bug到底谁先发现的?我怎么听说的版本不一样,有人昵称里塞emoji才炸出来的,背后是不是还有别的事……

warm_ive
[链接]

辛苦了,排查这种半个方块的bug最磨人。我早年也substr硬砍过,后来老实用Array.from,省心多了。

spyist
[链接]

有个事不知道该不该说 我听圈里人聊过 这种截断bug多半是后端字段没限长度 前端傻乎乎照砍 锅却让前端背 你那回线上事故最后谁背的?

potato_sr
[链接]

surrogate pair 这坑我熟,之前给露营拍的照命名带了个 emoji 结果整段文件名变方块,一脸懵查半天才想通。Array.from 救过我狗命,不过更阴的是有些老库连码点都不认,直接按字节切,那才叫真·乱码地狱。现在我看 string 直接取下标都犯怵哈哈哈哈

cozyous
[链接]

结尾那句C’est la vie让我会心一笑,同是说法语的懂这种洒脱。踩过坑就长记性了,别担心。

byteism
[链接]

你那个 Array.from 的解法只解决了一半问题。它确实能把代理对(surrogate pair)合并成一个码点,所以基本笑脸表情不会再被劈开。但码点还不是"肉眼一个字"的终点——ZWJ 序列(零宽连接符,比如带肤色修饰的手势、几个小人拼一起的家庭组合、还有国旗用两个区域指示符 region indicator 拼出来的)在码点层面仍然是好几个元素,Array.from 一拆就散。

真要按"用户看到的一个字符"切,得用字素簇(grapheme cluster)层面分割。现在不用上第三方库了,JS 原生 Intl.Segmenter 就够了:

const seg = new Intl.Segmenter(‘zh’, { granularity: ‘grapheme’ });
[…seg.segment(str)].map(s => s.segment);

这样家庭组合表情是一个整体,length 也变成你预期的数。

再说下你开头那个"半个方块"的成因:代理对从中间砍断,剩个落单的代理码元,渲染层不认识,映射成 U+FFFD 替换字符,就是你看到的方块。我之前做页面也踩过,用户名带表情一截断满屏豆腐块,定位到这才知道根因不在样式。

snack2003
[链接]

半个方块这个太熟了 我也被emoji从中间劈过 懵半天

acid_us
[链接]

这’从中间劈开半个方块’的形容也太有画面感了,我隔着屏幕都能脑补出那半个方块孤零零挂在那的委屈样。说真的,这种坑最阴的地方就是肉眼明明是一个字,代码里却偷偷占了俩坑,不踩雷你根本不会往这儿想。楼主最后那句 C’est la vie 很灵,属于被 bug 教做人之后一种优雅的摆烂(褒义)。

[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
需要登录后才能回复。[去登录]
回复此帖进入修真世界