HubSpot/humanize · 上手攻略
- 仓库:HubSpot/humanize
- 链接:https://github.com/HubSpot/humanize
- 分类:javascript · utility · formatting
- 作者:Tom
- 更新:2026-08-23
是什么
Humanize(npm 包名 humanize-plus)是 HubSpot 开源的 JavaScript 工具库,专注把机器数字和原始字符串格式化成人类可读的友好文本。比如把 123456789 变成 "123.5M",把 "hello world" 首字母大写成 "Hello world",把文件字节数 1024 * 2000 变成 "1.95 Mb"。
官方自称"making the web more humane",定位是前端展示层的数值/文本格式化辅助函数,适用于 Dashboard、报表、聊天界面等需要把原始数据变成可读文本的场景。
解决什么问题
前端开发中,把数字直接展示给用户往往体验很差:
- 数字没有千分位分隔符,阅读长数字困难(如
123456789vs123,456,789) - 字节数直接展示
1048576而不是1 Mb - 英文单词复数需要手写三元表达式(如
count === 1 ? 'duck' : 'ducks') - 列表展示手写
apple, orange, banana and 2 others格式繁琐 - 截断字符串手算字符数容易出 bug
Humanize 把这些格式化需求封装成 20+ 个独立函数,一行调用,无需手写重复逻辑。
快速安装
# npm 安装
npm install humanize-plus
# 或直接下载单文件(无依赖)
# 完整版:https://raw.github.com/HubSpot/humanize/master/src/humanize.js
# 压缩版:https://raw.github.com/HubSpot/humanize/master/dist/humanize.min.js
Web 页面直接引用(全局 Humanize 对象):
<script src="public/humanize.min.js"></script>
<script>
var capitalized = Humanize.capitalize("ten tiny ducklings.")
// "Ten tiny ducklings."
</script>
Node.js 项目在 package.json 添加依赖:
"dependencies": {
"humanize-plus": "^1.7.0"
}
然后:
const Humanize = require('humanize-plus');
// 或 ESM
import Humanize from 'humanize-plus';
⚠️ 包名是 humanize-plus,不是 humanize(后者是另一个不相关的包);版本 ^1.7.0 发布于 2016 年,后续无大版本更新,API 稳定。
核心用法
1. 数字格式化
// 精确小数位格式化(带千分位)
Humanize.formatNumber(123456789, 2)
// "123,456,789.00"
// 整数千分位(无小数)
Humanize.intComma(123456789)
// "123,456,789"
2. 大数字缩写
// 整数缩写(自动选择 K/M/B/T 单位)
Humanize.intWord(123456789)
// "123.5M" (注意:实际调用 compactInteger,效果相同)
// 科学计数法超大数字
Humanize.compactInteger(-7832186132456328967, 4)
// "-7.8322x10^18"
3. 文件大小
Humanize.fileSize(1024 * 20)
// "20 Kb"
Humanize.fileSize(1024 * 2000)
// "1.95 Mb"
Humanize.fileSize(Math.pow(1000, 4))
// "931.32 Gb"
⚠️ fileSize 的基准是 1024(KiB / MiB / GiB),不是 1000;这是存储行业的惯例,注意和部分系统用的十进制区分。
4. boundedNumber(上限标注)
Humanize.boundedNumber(110, 100)
// "100+"
Humanize.boundedNumber(50, 100)
// "50"
5. ordinal(序数词)
Humanize.ordinal(22)
// "22nd"
Humanize.ordinal(1)
// "1st"
Humanize.ordinal(3)
// "3rd"
6. times(次数的友好表达)
for (let i = 0; i < 5; i++) {
Humanize.times(i, {"4": "too many"});
if (i === 1) Humanize.times(1.1);
}
// never
// once
// 1.1 times
// twice
// 3 times
// too many times
支持自定义映射和 override 数组。
7. pace(速度友好描述)
const second = 1000;
const week = 6.048e8;
Humanize.pace(1.5, second, "heartbeat")
// "Approximately 2 heartbeats per second"
Humanize.pace(4, week)
// "Approximately 4 times per week"
8. pluralize(复数处理)
Humanize.pluralize(1, "duck")
// "duck"
Humanize.pluralize(3, "duck")
// "ducks"
Humanize.pluralize(3, "duck", "duckies")
// "duckies" (自定义复数后缀)
9. truncate / truncateWords(字符串截断)
Humanize.truncate('long text is good for you')
// "long text is good for you" (未超长,不截断)
Humanize.truncate('long text is good for you', 19)
// "long text is goo..."
Humanize.truncate('long text is good for you', 19, '... etc')
// "long text is... etc"
Humanize.truncateWords('long text is good for you', 5)
// "long text is good for ..."
10. capitalize / capitalizeAll / titleCase(大小写)
Humanize.capitalize("some boring string")
// "Some boring string"
Humanize.capitalize("wHoOaA!")
// "WHoOaA!" (仅首字母大写,不动其余字符)
Humanize.capitalize("wHoOaA!", true)
// "Whooaa!" (第二个参数 true = 其余字符转小写)
Humanize.capitalizeAll("some boring string")
// "Some Boring String"
Humanize.titleCase("some of a boring string")
// "Some of a Boring String" (虚词小写,iTunes 等特殊处理)
11. oxford(牛津列表格式)
const items = ['apple', 'orange', 'banana', 'pear', 'pineapple'];
Humanize.oxford(items)
// "apple, orange, banana, pear, and pineapple"
Humanize.oxford(items, 3)
// "apple, orange, banana, and 2 others"
Humanize.oxford(items, 4)
// "apple, orange, banana, pear, and 1 other"
Humanize.oxford(items, 3, "and some other fruits")
// "apple, orange, banana, and some other fruits"
12. frequency(出现次数描述)
const catPics = [
'https://media2.giphy.com/media/JIX9t2j0ZTN9S/giphy.gif',
'https://media3.giphy.com/media/uzglgIsyY1Cgg/giphy.gif'
];
"Cats " + Humanize.frequency(catPics, "typed on keyboards")
// "Cats typed on keyboards 3 times"
const dogPics = [];
"Dogs " + Humanize.frequency(dogPics, "typed on keyboards")
// "Dogs never typed on keyboards"
13. toFixed(修复浮点精度问题)
Humanize.toFixed(0.615, 2)
// "0.62" (解决了 (0.615).toFixed(2) === "0.61" 的二进制舍入问题)
Humanize.normalizePrecision(-232.231)
// 232 (取正整数精度值)
典型适用场景
- Dashboard 数值展示:把原始字节数、毫秒级延迟、用户数等直接展示为友好格式。
- 聊天机器人回复:生成"处理了 3 个文件"而不是"处理了 3 个文件(复数)"这类文字。
- 通知/推送文案:邮件/推送里需要动态拼接用户数据,一行调用解决复数和格式化。
- 数据分析报告:导出 CSV/Excel 前在 JS 层做格式化,保证前端展示和导出数据一致。
- SEO 友好的 URL 文本:titleCase 生成页面标题、描述文字。
坑与注意
| 坑点 | 说明 |
|---|---|
包名是 humanize-plus |
npm 上搜索 humanize 会找到另一个不相关的包,注意甄别 |
| 版本停留在 1.7.x | 最后更新约 2016 年,无 ESM 原生支持、无 Tree-shaking;现代项目建议自行打包 |
fileSize 用 1024 基准 |
存储行业惯例,部分 UI 需要显示十进制(1000 基准)时需要自己换算 |
capitalize 不自动转小写余部 |
除非传第二个参数 true,否则 wHoOaA! → WHoOaA! 而非 Whooaa! |
| 中文场景直接用价值有限 | titleCase 对英文效果显著;中文场景主要靠 intComma、fileSize、pluralize |
| 不支持复数语言本地化 | pluralize 只支持英语单复数,多语言项目需要 i18n 方案 |
| cdnjs 版本可能旧 | 如用 CDN 引入,确认 cdnjs 上版本号;建议直接 npm 安装 |
与同类对比
| 工具 | 体积 | 功能覆盖 | 特殊能力 | 适合场景 |
|---|---|---|---|---|
| humanize-plus | ~4 KB gzip | 数字+文本格式化 | toFixed 精度修复、oxford 列表 |
轻量仪表盘、展示层 |
| Numeral.js | ~6 KB | 数字格式化为主 | 多语言数字格式 | 需要复杂数字格式 |
| Moment.js / dayjs | 较大 | 时间处理 | 时间计算/解析/本地化 | 时间相关场景 |
| date-fns | 中等 | 时间处理 | 函数式组合 | 时间场景(无复数/文本处理) |
| lodash | 较大 | 通用工具 | 一切 | 庞大项目,多处用到工具函数 |
| Intl API(原生) | 0 KB | 数字/日期本地化 | 浏览器原生无依赖 | 现代浏览器环境 |
Humanize-plus 的核心优势是轻量 + 即插即用,一个文件覆盖前端展示层 80% 的格式化需求,无需引入 Moment/lodash 这类重型库。
一句话推荐结论
一个小于 4 KB 的前端格式化工具库,
intComma、fileSize、pluralize、oxford等 20+ 函数覆盖 Dashboard / 聊天机器人 / 推送文案等场景的常见需求——直接 npm 装,不需要为这些简单需求引入 lodash 或 moment。
源码编译(如需贡献)
npm run install && npm run build
# 编译 CoffeeScript 源码到 dist/
npm run test
# 运行测试