惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
T
Threatpost
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
S
Secure Thoughts
MyScale Blog
MyScale Blog
O
OpenAI News
P
Palo Alto Networks Blog
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
TaoSecurity Blog
TaoSecurity Blog
量子位
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Know Your Adversary
Know Your Adversary
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Simon Willison's Weblog
Simon Willison's Weblog
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
I
InfoQ
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
S
Security @ Cisco Blogs
S
Schneier on Security
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
AWS News Blog
AWS News Blog
IT之家
IT之家
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
H
Heimdal Security Blog
I
Intezer
A
Arctic Wolf
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
W
WeLiveSecurity

张鑫旭-鑫空间-鑫生活

1分钟速度了解text-align match-parent声明 « 张鑫旭-鑫空间-鑫生活 光标的形状也能设置了,就是CSS caret-shape属性 « 张鑫旭-鑫空间-鑫生活 pretext与文字四面环绕效果的实现 « 张鑫旭-鑫空间-鑫生活 JSON.rawJSON方法的作用是什么? « 张鑫旭-鑫空间-鑫生活 如何使用CSS判断鼠标从哪个方向进入元素? « 张鑫旭-鑫空间-鑫生活 借助mediabunny纯JS实现视频水印、剪裁、合成等功能 « 张鑫旭-鑫空间-鑫生活 务必谨慎使用JS WeakRef弱引用 « 张鑫旭-鑫空间-鑫生活 CSS六边形头像的实现与蜂巢布局 « 张鑫旭-鑫空间-鑫生活 CSS corner-shape与背景底纹技术 « 张鑫旭-鑫空间-鑫生活 浅学WebTransport API:下一代Web双向通信技术 « 张鑫旭-鑫空间-鑫生活 HTML dialog元素新支持了closedBy属性 « 张鑫旭-鑫空间-鑫生活 HTML interestfor属性与悬停popover交互效果 « 张鑫旭-鑫空间-鑫生活 CSS3模拟window7炫酷界面效果展示 « 张鑫旭-鑫空间-鑫生活 图片旋转+剪裁js插件(兼容各浏览器) « 张鑫旭-鑫空间-鑫生活 纯js无图片无外链CSS图片幻灯片播放插件 « 张鑫旭-鑫空间-鑫生活 CSS border三角、圆角图形生成技术简介 « 张鑫旭-鑫空间-鑫生活 CSS “渐进增强”在web制作中常见应用举例 « 张鑫旭-鑫空间-鑫生活 让IE6/IE7/IE8浏览器支持CSS3属性 « 张鑫旭-鑫空间-鑫生活 jQuery – 高亮动态显示页面HTML代码插件 « 张鑫旭-鑫空间-鑫生活 翻译 – 逐渐消失的Flash网站 « 张鑫旭-鑫空间-鑫生活 CSS reset的重新审视 – 避免样式重置 « 张鑫旭-鑫空间-鑫生活 新浪微博插入话题后部分文字选中的js实现 « 张鑫旭-鑫空间-鑫生活 JavaScript实现http地址自动检测并添加URL链接 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变背景(gradient)效果 « 张鑫旭-鑫空间-鑫生活 CSS content内容生成技术以及应用 « 张鑫旭-鑫空间-鑫生活 CSS gradient渐变之webkit核心浏览器下的使用 « 张鑫旭-鑫空间-鑫生活 CSS渐变之CSS3 gradient在Firefox3.6下的使用 « 张鑫旭-鑫空间-鑫生活 区分IE8/IE7/IE6及其他浏览器-CSS “\9″hack « 张鑫旭-鑫空间-鑫生活 CSS实现跨浏览器兼容性的盒阴影效果 « 张鑫旭-鑫空间-鑫生活 CSS3&HTML5各浏览器支持情况一览表 « 张鑫旭-鑫空间-鑫生活 翻译 – CSS Sprites:实用技术还是生厌之物? « 张鑫旭-鑫空间-鑫生活 纯CSS实现易拉罐3D滚动效果 « 张鑫旭-鑫空间-鑫生活 纯CSS实现侧边栏/分栏高度自动相等 « 张鑫旭-鑫空间-鑫生活 CSS+JavaScript实现页面不同布局的切换 « 张鑫旭-鑫空间-鑫生活 JavaScript实现最简单的拖拽效果 « 张鑫旭-鑫空间-鑫生活 自己写的无图片版jQuery zxxbox弹出框插件 « 张鑫旭-鑫空间-鑫生活 中国古代道家思想与网页重构的思考 « 张鑫旭-鑫空间-鑫生活 让所有浏览器支持HTML5 video视频标签 « 张鑫旭-鑫空间-鑫生活 纯CSS实现各类气球泡泡对话框效果 « 张鑫旭-鑫空间-鑫生活 JS HEX十六进制与RGB, HSL颜色的相互转换 « 张鑫旭-鑫空间-鑫生活 CSS实现兼容性的渐变、高光等文字效果 « 张鑫旭-鑫空间-鑫生活 去除冗余 – 精简您的CSS样式代码 « 张鑫旭-鑫空间-鑫生活 对overflow与zoom”清除浮动”的一些认识 « 张鑫旭-鑫空间-鑫生活 jQuery Pagination Ajax分页插件中文详解 « 张鑫旭-鑫空间-鑫生活 absolute绝对定位的非绝对定位用法 « 张鑫旭-鑫空间-鑫生活 网页布局思想浅议-淘宝新版首页为实例 « 张鑫旭-鑫空间-鑫生活 回流与重绘:CSS性能让JavaScript变慢? « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(二) « 张鑫旭-鑫空间-鑫生活 CSS float浮动的深入研究、详解及拓展(一) « 张鑫旭-鑫空间-鑫生活 60个极富创造性的震撼的电影海报设计 « 张鑫旭-鑫空间-鑫生活 jQuery Lightbox(balupton版)图片展示插件讲解 « 张鑫旭-鑫空间-鑫生活 博客内嵌flash音乐播放器代码、下载与使用 « 张鑫旭-鑫空间-鑫生活 CSS3 animate实现图片墙3D翻转效果 « 张鑫旭-鑫空间-鑫生活 图片旋转效果的一些研究、jQuery插件及实例 « 张鑫旭-鑫空间-鑫生活 CSS3 border-image详解、应用及jQuery插件 « 张鑫旭-鑫空间-鑫生活 jQuery-两款不同原理的圆角插件讲解 « 张鑫旭-鑫空间-鑫生活 页面可用性之outline轮廓外框的一些研究 « 张鑫旭-鑫空间-鑫生活 CSS3 transition实现超酷图片墙动画效果 « 张鑫旭-鑫空间-鑫生活 HTML CSS列表元素ul,ol,dl的研究与应用 « 张鑫旭-鑫空间-鑫生活 jQuery图片文本滚动切换插件jCarousel中文翻译与详解 « 张鑫旭-鑫空间-鑫生活 酷酷的jQuery鼠标悬停图片放大切换显示效果 « 张鑫旭-鑫空间-鑫生活 IE6下z-index犯癫不起作用bug的初步研究 « 张鑫旭-鑫空间-鑫生活 checkbox复选框的一些深入研究与理解 « 张鑫旭-鑫空间-鑫生活 jQuery之使用slideToggle实现垂直下拉菜单 « 张鑫旭-鑫空间-鑫生活 jQuery-innerfade内部列表自动淡入淡出插件 « 张鑫旭-鑫空间-鑫生活 jQuery-火焰灯效果导航菜单 « 张鑫旭-鑫空间-鑫生活 IE下css bug集合-翻译自haslayout.net « 张鑫旭-鑫空间-鑫生活 翻译-IE7/8@font-face嵌入字体与文字平滑 « 张鑫旭-鑫空间-鑫生活 jQuery-马化腾产品设计与用户体验的一些技术实现 « 张鑫旭-鑫空间-鑫生活 像素的世界及其在web开发制作中的应用 « 张鑫旭-鑫空间-鑫生活 css行高line-height的一些深入理解及应用 « 张鑫旭-鑫空间-鑫生活 CSS实现圆角六色渐变自适应按钮详解 « 张鑫旭-鑫空间-鑫生活 我熟知的三种三栏网页宽度自适应布局方法 « 张鑫旭-鑫空间-鑫生活 jQuery照片图像剪裁插件Jcrop中文翻译详解 « 张鑫旭-鑫空间-鑫生活 Ajax Upload多文件上传插件翻译及中文演示 « 张鑫旭-鑫空间-鑫生活 告别图片—使用字符实现兼容性的圆角尖角效果beta版 « 张鑫旭-鑫空间-鑫生活 大小不固定的图片、多行文字的水平垂直居中 « 张鑫旭-鑫空间-鑫生活 jQuery boxy弹出层对话框插件中文演示及讲解 « 张鑫旭-鑫空间-鑫生活 JavaScript实现新浪微博文字放大显示动画效果 « 张鑫旭-鑫空间-鑫生活 翻译:让网络更快一些——最小化浏览器中的回流(reflow) « 张鑫旭-鑫空间-鑫生活 jQuery之addClasas与removeClass使用实例 « 张鑫旭-鑫空间-鑫生活 关于Google圆角高光高宽自适应按钮及其拓展 « 张鑫旭-鑫空间-鑫生活 JavaScript实现图片幻灯片滚动播放动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery-鼠标经过显示大图并跟随鼠标效果插件 « 张鑫旭-鑫空间-鑫生活 关于gif图片(或png8)杂边锯齿的问题 « 张鑫旭-鑫空间-鑫生活 对html与body的一些研究与理解 « 张鑫旭-鑫空间-鑫生活 鲜为人知的一个解决兼容性问题的利器——小数 « 张鑫旭-鑫空间-鑫生活 搜狐白社会似iphone短信对话框效果的优化 « 张鑫旭-鑫空间-鑫生活 关于文字内容溢出用点点点(…)省略号表示 « 张鑫旭-鑫空间-鑫生活 jquery之append与insertBefore使用实例 « 张鑫旭-鑫空间-鑫生活 jQuery之图片关联伸缩效果 « 张鑫旭-鑫空间-鑫生活 jquery之图片左右切换动画效果 « 张鑫旭-鑫空间-鑫生活 jQuery之replace字符串替换实现不同尺寸图片切换 « 张鑫旭-鑫空间-鑫生活 jQuery-实现图片的放大镜显示效果 « 张鑫旭-鑫空间-鑫生活 jQuery-单击文字或图片内容放大显示效果插件 « 张鑫旭-鑫空间-鑫生活 reflection.js-实现图片投影倒影效果js插件 « 张鑫旭-鑫空间-鑫生活 jQuery-很酷的弹出层效果js插件 « 张鑫旭-鑫空间-鑫生活 复选框单选框与文字对齐问题的研究与解决 « 张鑫旭-鑫空间-鑫生活 css margin的相关属性,问题及应用 « 张鑫旭-鑫空间-鑫生活 IE6下png背景不透明问题的综合拓展 « 张鑫旭-鑫空间-鑫生活
使用Intl.Segmenter返回更准确的字符长度 « 张鑫旭-鑫空间-鑫生活
张鑫旭,zhangxinxu · 2025-09-30 · via 张鑫旭-鑫空间-鑫生活

by zhangxinxu from https://www.zhangxinxu.com/wordpress/?p=11883
本文可全文转载,但需要保留原作者、出处以及文中链接,AI抓取保留原文地址,任何网站均可摘要聚合,商用请联系授权。

分词与字符长度

一、Emoji字符长度问题

我们平常获取字符串的长度都是直接使用length属性,但对于某些字符,返回的结果会在预期之外,例如:

"鑫空间".length

"🌝".length

"🇮🇳".length

"👨‍👩‍👧‍👦".length

"दरबार".length

结果如下:

"鑫空间".length // 3

"🌝".length    // 2

"🇮🇳".length    // 4

"👨‍👩‍👧‍👦".length    // 11

"दरबार".length  // 5

看到没,看起来Emoji表情字符的长度是1,但是,实际返回的Emoji长度并不是1,不仅不是1,不同的Emoji返回的长度还不一样,这就会给我们精确统计字符长度带来困扰。

怎么办呢?

二、返回字符的真实长度

我们可以使用Intl.Segmenter()返回字符串的真实长度:

Array.from(
  new Intl.Segmenter("en", {
    // 颗粒度:字位,默认值,可省略
    granularity: "grapheme" 
  }).segment(this)
).length

不过上面代码不太好记忆,我们不妨给字符串扩展一个名为 realLength 的方法,完整代码如下所示:

Object.defineProperty(String.prototype, 'realLength', {
  get: function() {
    return Array.from(
      new Intl.Segmenter("en").segment(this)
    ).length;
  }
});

此时,我们就可以返回字符串真实的长度了。

"鑫空间".realLength // 3

"🌝".realLength    // 1

"🇮🇳".realLength    // 1

"👨‍👩‍👧‍👦".realLength    // 1

"दरबार".realLength  // 4

是不是很美丽?

紫灵

三、Emoji字符长度不是1的原因

JavaScript使用UTF-16编码,这种编码方式最多支持 2x 16 共 65,536 个字符,6万多个字符看起来多,但是世界上那么多语言,已经不够用了,尤其Emoji表情字符,都在65,536 个字符开外。

JS想要表示,只能组合多个特殊的 2 字节代码单元以生成人类可读的字符。

例如:

Array.from({ length: "🌝".length }, (_, i) => "🌝"[i])
// [ '\ud83c', '\udf1d' ]

于是,JS代码直接使用length属性访问的时候,返回值就是2,但是人类理解肯定是1个字符。

这就是Emoji字符长度不是1的原因。

另外补充一点,不少开发人员直接使用Array.from()方法返回长度,就像这样:

Array.from("🌝").length; // 结果是1

但是,并不是所有Emoji都返回的是1,例如:

Array.from("👨‍👩‍👧‍👦").length; // 结果是7

返回的长度就是7,就不对了。

四、关于Intl.Segmenter

Intl.Segmenter 是 JavaScript 中一个专门用于文本分段的强大工具,它能够根据不同的语言和文本规则,将字符串智能地分割成有意义的单位,如字符、单词或句子。

核心概念与语法

Intl.Segmenter 的核心作用在于进行语言敏感的分段。

传统的字符串分割方法(如 split(‘ ‘))对于英语这类使用空格分隔单词的语言勉强适用,但对于中文、日文等不依赖空格的语言就无能为力了,甚至处理包含复杂表情符号(Emoji)的文本时也会出错。

Intl.Segmenter 则依据 Unicode 标准,能够理解不同语言的语法习惯,进行精准的边界检测。

使用示意:

const segmenter = new Intl.Segmenter([locales[, options]]);

其中:

locales
表示语言,使用一个 BCP 47 语言标签的字符串,如 “zh-CN”、”en-US”、”ja”等。它指定了分段所依据的语言规则。如果省略,则会使用运行时环境的默认语言设置。
options
可选参数,包括下面这些:

granularity

表示分段的粒度,是最重要的选项。可取值为:

  • “grapheme”(默认值):在用户感知的字符(字形簇)边界分割。例如,一个基础字符加上修饰符(如 “a” + “́” 组成 “á”)会被视为一个整体,复杂的 Emoji 序列(如家庭表情 👨‍👩‍👧‍👦)也不会被拆散。
  • “word”:在单词边界分割。它能正确识别中文的词汇单元(如将“我真的很强”分割为“我”、“真的”、“很”、“强”),并能区分标点符号和空格(isWordLike 属性为 false)。
  • “sentence”:在句子边界分割。它能智能区分句号的不同用途,例如不会将数字 “100.000” 中的点号误判为句子结束。

localeMatcher

指定所使用的语言匹配算法,可以是 “best fit”(默认值,使用环境提供的可能最匹配的算法)或 “lookup”(使用特定的 BCP 47 算法)。

基本使用方法

创建分段器实例后,通过调用其 segment(inputString) 方法对文本进行分段。该方法返回一个 Segments 可迭代对象。

例如:

// 创建一个中文词段器
const segmenter = new Intl.Segmenter('zh-CN', { granularity: 'word' });
const text = "《HTML并不简单》是国内唯一一本精讲HTML的技术书籍";
const segments = segmenter.segment(text); // 返回一个 Segments 对象

// 遍历
for (const segment of segments) {
  console.log(`片段: "${segment.segment}", 起始索引: ${segment.index}, 是否像词: ${segment.isWordLike}`);
}

在我的Chrome浏览器下,输出的结果是:

// 片段: "《", 起始索引: 0, 是否像词: false
// 片段: "HTML", 起始索引: 1, 是否像词: true
// 片段: "并不", 起始索引: 5, 是否像词: true
// 片段: "简单", 起始索引: 7, 是否像词: true
// 片段: "》", 起始索引: 9, 是否像词: false
// 片段: "是", 起始索引: 10, 是否像词: true
// 片段: "国内", 起始索引: 11, 是否像词: true
// 片段: "唯一", 起始索引: 13, 是否像词: true
// 片段: "一本", 起始索引: 15, 是否像词: true
// 片段: "精", 起始索引: 17, 是否像词: true
// 片段: "讲", 起始索引: 18, 是否像词: true
// 片段: "HTML", 起始索引: 19, 是否像词: true
// 片段: "的", 起始索引: 23, 是否像词: true
// 片段: "技术", 起始索引: 24, 是否像词: true
// 片段: "书籍", 起始索引: 26, 是否像词: true

可以看到浏览器自带对中文句子进行分词了。

兼容性

目前Intl.Segmenter所有现代浏览器均已支持,前端也能自动分词分句了。

Intl.Segmenter兼容性

五、结语

Intl命名对象还有很多其他方法,多是与语言、金钱、数字、字符处理相关的。

详见我之前的这篇文章:“JS Intl对象完整简介及在中文中的应用

还是非常强大与实用的。

就是语法复杂了点,学习成本比较高,真正使用的时候,需要去搜索查找资料。

不过现在都有AI了,只需要知道有这么个东西就好了,AI会帮你搞定。

行吧,就说这么多。

明天就是国庆节了,祝大家国庆节快乐!

不说了,我要准备出发去钓鱼了!

欢迎大家关注我的钓鱼账号:“最会钓鱼的程序员”。

随时了解我国庆节的战况。

张鑫旭本人

😉😊😇
🥰😍😘

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=11883

(本篇完)