按场景分类的JavaScript专用函数库清单:日期处理、HTTP请求与数据格式化

作者:纸飞机

时间:2026-11-06

浏览:222

按场景分类的JavaScript专用函数库实用清单,深入分析日期时间处理、HTTP网络请求与数据格式化三大高频场景下的主流专用库、选型路径、架构原理与代码实践。

文章目录
通用实用工具库(如 Lodash、Ramda)虽然覆盖了基础集合与对象遍历,但在日期时区计算、网络通信生命周期以及业务数据精度格式化等专业垂直领域,通用库无法提供深度抽象,而原生 JavaScript API 又常伴随易变性、隐式类型转换或平台行为差异。解决这一矛盾的有效路径,是按具体业务场景选用职责单一、设计健壮的专用函数库。本文梳理日期处理、HTTP 请求与数据格式化三大高频场景的主流方案,提供客观选型边界、代码范式与工程实践指导。
按场景分类的JavaScript专用函数库清单:日期处理、HTTP请求与数据格式化
图 1:按场景分类的 JavaScript 专用函数库全景映射

一、日期与时间处理专用库

JavaScript 原生的 Date 对象存在多项历史设计缺陷:其实例是可变的(Mutable),任何计算方法(如 setMonth)都会原地修改原始对象,极易引发难以排查的引用污染;月份基于 0 索引(0 代表一月)容易产生认知差错;时区支持依赖宿主环境,缺乏对 IANA 时区标识符的原生跨平台计算能力。虽然 TC39 正在推进全新的 Temporal 标准,但在该标准全面普及与各环境完全稳定支持之前,业务系统仍需依赖可靠的专用日期库。

选型明确判断:关于 Moment.js 的维护状态

Moment.js 官方团队早已宣布项目进入维护模式(Maintenance Mode),不再增加新功能,并明确建议新项目不要选用。其核心问题在于对象可变性与庞大的包体积(未 Gzip 超过 200KB,且因链式设计难以被现代打包工具 Tree-shaking)。现代项目应当全面迁移至不可变函数式或插件化的现代替代方案。

1. 主流专用日期库核心差异与选型

  • date-fns:倡导“日期的 Lodash”理念。所有方法均为纯函数,输入原生 Date 并返回新 Date,天然不可变。完全支持 ESM 模块化导入,Tree-shaking 表现优异,大型复杂前端工程与函数式架构推荐首选。
  • Day.js:与 Moment.js 保持高度一致的链式语法,但将包体积压缩至约 2KB。其核心设计同样基于不可变数据,且采用微内核与插件机制(如时区、相对时间均以插件按需注册),非常适合移动端 H5 及体积敏感型项目。
  • Luxon:由 Moment.js 维护团队核心成员开发,深度依托现代浏览器原生的 Intl 国际化规范。对夏令时、IANA 时区转换、ISO 持续时间解析提供了极严谨的支持,适合跨国出海、涉外航班预订、金融计息等强时区依赖场景。
按场景分类的JavaScript专用函数库清单:日期处理、HTTP请求与数据格式化
图 2:日期处理库工程选型路径与接入操作流程

2. 典型实战代码示例

以下示例展示了 date-fns 与 Day.js 在安全加减计算与格式化上的规范写法:

// 示例 1:使用 date-fns 进行纯函数按需计算(Tree-shaking 友好)
import { addDays, subHours, format, differenceInCalendarDays } from 'date-fns';
import { zhCN } from 'date-fns/locale';

const baseTime = new Date('2026-11-05T08:00:00Z');

// 纯函数计算:不改变 baseTime 本身,生成全新实例
const futureDeadline = addDays(baseTime, 7);
const adjustedTime = subHours(futureDeadline, 2);

console.log('格式化输出:', format(adjustedTime, 'yyyy年MM月dd日 HH:mm', { locale: zhCN }));
// 示例输出: "2026年11月12日 06:00"

const diffDays = differenceInCalendarDays(futureDeadline, baseTime);
console.log('相隔天数:', diffDays); // 7
// 示例 2:使用 Day.js 引入按需插件处理相对时间与 UTC
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import utc from 'dayjs/plugin/utc';
import 'dayjs/locale/zh-cn';

// 严格按需注册插件并切换语言
dayjs.extend(relativeTime);
dayjs.extend(utc);
dayjs.locale('zh-cn');

const postDate = dayjs('2026-11-01T12:00:00Z');
console.log('相对发布时间:', postDate.fromNow()); // 示例输出: "4 天前"
console.log('UTC 偏移格式化:', postDate.utc().format('YYYY-MM-DD HH:mm:ss [UTC]'));

二、HTTP 网络请求与通信专用库

虽然现代浏览器与 Node.js 均已内置了标准的 fetch API,但在企业级工程实践中,裸调 fetch 往往需要编写大量胶水代码:例如 fetch 遇到 HTTP 404 或 500 状态码时默认不会 reject,必须手工检查 response.ok;反序列化 JSON 必须额外调用 res.json();缺少开箱即用的超时取消与重试机制;更重要的是缺乏全局请求/响应双向拦截管道。专用网络库正是为了弥补这些工程层面的短板。

1. 主流专用 HTTP 请求库对比

  • Axios:跨端同构的事实标准。在浏览器端底层封装 XMLHttpRequest 或 fetch,在 Node.js 端封装原生 http/https 模块。具备完备的请求/响应拦截器链、自动转换 JSON 数据、内置 XSRF 防御支持,在中后台与大型全栈系统中成熟度最高。
  • Ky:面向现代运行时的优雅轻量方案(约 3.5KB)。基于原生 fetch 封装,专为现代浏览器和 Node 18+ 环境设计。内置指数退避重试、精确超时(基于 AbortController 封装)、便捷的 ky.get(...).json() 链式调用,代码体积与体验平衡极佳。
  • wretch:体积仅约 2KB 的超轻量 fetch 包装器。最大亮点在于直观的状态码条件分流(如 .notFound(...)、.unauthorized(...)),极大简化了对不同 HTTP 响应分支的差异化处理。
按场景分类的JavaScript专用函数库清单:日期处理、HTTP请求与数据格式化
图 3:HTTP 请求处理管道与双向拦截架构

2. 请求拦截与无感刷新 Token 实践

在企业级客户端中,统一注入身份凭证并对 401 凭证失效进行静默刷新,是专用请求库最具代表性的应用场景:

// 示例 3:Axios 单例客户端封装与双向拦截器闭环
import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 8000,
  headers: { 'Content-Type': 'application/json' }
});

// 1. 请求拦截器:动态注入鉴权凭证与链路追踪 ID
apiClient.interceptors.request.use((config) => {
  const token = localStorage.getItem('access_token');
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  config.headers['X-Request-Trace'] = crypto.randomUUID();
  return config;
}, (error) => Promise.reject(error));

// 2. 响应拦截器:统一剥离外层包装,捕获 401 自动触发重试
apiClient.interceptors.response.use(
  (response) => response.data, // 业务直接获取脱壳数据
  async (error) => {
    const originalRequest = error.config;
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        // 调用刷新接口获取新凭据
        const { data } = await axios.post('https://api.example.com/v1/auth/refresh');
        localStorage.setItem('access_token', data.new_token);
        originalRequest.headers.Authorization = `Bearer ${data.new_token}`;
        return apiClient(originalRequest); // 无感重新执行当前请求
      } catch (refreshError) {
        localStorage.removeItem('access_token');
        window.location.href = '/login';
        return Promise.reject(refreshError);
      }
    }
    return Promise.reject(error);
  }
);

三、数据格式化与校验专用库

前端展现和业务计算对数据呈现有严格的准确性要求。JavaScript 采用 IEEE 754 双精度浮点数标准,直接进行金额计算会遭遇经典精度问题(如 0.1 + 0.2 === 0.30000000000000004);而接口返回的数据结构如果不做运行时防御与清洗,容易导致模板渲染出现 Cannot read properties of undefined。因此,数据层面的专用库聚焦于高精度算术、模式校验清洗与字符命名规范化三大维度。

按场景分类的JavaScript专用函数库清单:日期处理、HTTP请求与数据格式化
图 4:数据清洗、校验与格式化操作流水线

1. 货币与高精度数值处理:currency.js

在电商结算、购物车统计与财务报表场景下,严禁使用原生 JavaScript 浮点数直接相加减。currency.js 内部将所有数值以基底整数(如精确到“分”)形式安全存储并执行计算,彻底规避浮点漂移,同时提供格式化千分位展示。

// 示例 4:currency.js 安全金额计算与格式化
import currency from 'currency.js';

const CNY = (val) => currency(val, { symbol: '¥ ', precision: 2 });

const itemPrice = CNY('19.99');
const quantity = 3;
const couponDiscount = CNY('5.00');

// 链式安全运算:内部无精度丢失
const finalTotal = itemPrice.multiply(quantity).subtract(couponDiscount);

console.log('格式化金额:', finalTotal.format()); // "¥ 54.97"
console.log('数值输出:', finalTotal.value);     // 54.97
原生替代选项:什么时候使用 Intl.NumberFormat?

如果业务只需要纯展示(不需要在客户端进行加减乘除算术运算),现代浏览器原生支持的 Intl.NumberFormat('zh-CN', { style: 'currency', currency: 'CNY' }) 是零打包开销的最佳选择。而一旦涉及运算、四舍五入与防截断,则必须引入 currency.js 等专用算术库。

2. 运行时模式校验与数据清洗转换:Zod

传统的格式化往往停留在把现成字段转成特定字符串,但更稳固的工程范式是在数据进入业务逻辑的第一道关口,使用 Zod 校验接口数据,并在校验流程中通过 .transform() 完成清洗、类型收敛与格式归一。

// 示例 5:使用 Zod 执行数据契约校验与流式清洗转换
import { z } from 'zod';

const UserResponseSchema = z.object({
  id: z.number().int().positive(),
  rawPhone: z.string().transform((val) => val.replace(/\D/g, '')), // 移除非数字字符
  balanceStr: z.string().transform((val) => Number.parseFloat(val) || 0), // 字符串安全转浮点
  registeredAt: z.string().datetime().transform((val) => new Date(val)), // ISO 字符串转 Date
  tags: z.array(z.string()).default([])
});

// 模拟不可信外部输入
const rawApiPayload = {
  id: 1042,
  rawPhone: ' +86 138-0013-8000 ',
  balanceStr: '128.50',
  registeredAt: '2026-11-05T07:20:00Z'
};

const cleanUser = UserResponseSchema.parse(rawApiPayload);
console.log(cleanUser.rawPhone);     // "8613800138000" (已清洗)
console.log(cleanUser.registeredAt); // 原生 Date 实例,可安全传递给下游函数

3. 文本与标识符命名法转换:change-case

后端接口常习惯下划线命名法(snake_case),而前端组件模型遵循驼峰命名(camelCase),URL 参数则采用短横线(kebab-case)。change-case 提供了完备且按需导入的命名转换纯函数,避免开发者自行编写带有漏洞的正则表达式。

// 示例 6:按需导入 change-case 进行字段风格转换
import { camelCase, pascalCase, kebabCase } from 'change-case';

console.log(camelCase('order_item_status')); // "orderItemStatus"
console.log(pascalCase('user_profile_card')); // "UserProfileCard"
console.log(kebabCase('ComponentPropsName'));  // "component-props-name"

四、综合选型决策矩阵与工程落地建议

在实际项目落地时,选择函数库不应只看功能多寡,更要权衡包体积(Bundle Size)、运行时环境、Tree-shaking 亲和度以及团队维护成本。下表汇总了本文介绍的核心专用库在多项技术指标上的横向比对:

按场景分类的JavaScript专用函数库清单:日期处理、HTTP请求与数据格式化
图 5:三大场景专用函数库综合选型决策矩阵
分类场景 推荐专用库 包体积 (Gzipped) 不可变性 Tree-shaking 核心适用场景
日期时间 date-fns 按需(百字节级) 天然不可变(纯函数) 优秀(ESM 导出) 现代大型 Web 工程、模块化与函数式架构
日期时间 Day.js ~2 KB (基础核心) 天然不可变 一般(依赖插件分离) 移动端 H5、后台管理系统轻量展示
日期时间 Luxon ~20 KB 天然不可变 良好 跨国涉外业务、国际化航空/金融强时区应用
HTTP 网络 Axios ~13 KB N/A 较弱(整体打包) 企业级中后台、需双向拦截与同构 Node.js 系统
HTTP 网络 Ky ~3.5 KB N/A 良好 现代浏览器与 Edge 运行时、追求轻量与重试机制
数据格式化 currency.js ~1.1 KB 不可变数据链 良好 电商结算、财务出账、需要精确四舍五入场景
数据格式化 Zod ~14 KB 类型不可变 优秀 全栈 TypeScript 契约校验、数据输入清洗与转换
数据格式化 change-case 按需 (<1 KB) 纯函数处理 优秀 接口字段风格映射、动态路由参数与命名转换
工程落地三项禁忌提醒

1. 严禁同项目混用同质库:同一代码库中严禁既安装 Day.js 又引入 date-fns,这会导致团队心智混乱并成倍增加包体积。
2. 严禁业务组件直接深依赖底层库:建议在工程目录中建立统一的适配层(如 utils/request.ts、utils/date.ts、utils/currency.ts),业务组件只调用统一导出的工具函数。未来若需调整底层实现,只需修改适配层单点。
3. 正确权衡原生标准:如果功能仅限于最基础的只读本地化展示,优先使用浏览器内置的 Intl 族标准对象(如 Intl.DateTimeFormat 与 Intl.NumberFormat),在零体积成本的前提下实现标准展示。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章