原生JS与Day.js获取当前月份的代码对比

作者:代码拾荒时间:2026-11-02 09:17:25浏览:74

本文系统对比原生JavaScript与Day.js获取当前月份的代码实现,深入解析0~11索引机制、前导补零、年月组合格式化及API设计差异,提供清晰实用的选型建议。

原生JS与Day.js获取当前月份的代码对比
在 JavaScript 开发中获取“当前自然月份”,最核心的区别在于原生 Date.prototype.getMonth() 采用 0 ~ 11 的下标索引机制,必须手动执行 + 1 并配合 padStart(2, '0') 才能得到带前导零的常见展示格式;而轻量级日期库 Day.js 在保留底层 month() 方法兼容性的同时,通过声明式的 format('M') 与 format('MM') 模板,直接输出无偏移或已补零的月份字符串。本文将通过真实代码对照、底层原理拆解与选型导图,完整梳理两者的具体语法、关键差异与适用边界。

一、核心机制差异:为什么原生 JS 需要“+ 1”

初学者在使用原生 JavaScript 的 Date 对象时,最容易写出的错误代码便是直接通过 new Date().getMonth() 获取月份并当成现实自然月份使用。执行后会发现,如果当前是 11 月,方法返回的数字却是 10。

这一设计的历史根源来自早期 C 语言标准库中的 struct tm 结构体以及 Java 1.0 时期的 java.util.Date。在当时的语言设计中,开发者习惯将月份作为英文月份名称数组(如 ['Jan', 'Feb', ..., 'Dec'])的下标索引,因此将 1 月对应为 0,12 月对应为 11。虽然随后的 ECMAScript 标准历经数十年演进,但为了维持向后兼容性,getMonth() 的 0 索引规范被永久保留了下来。

相比之下,现代化日期库 Day.js 采取了更为务实的“双轨设计”:

  • 底层兼顾计算(Getter/Setter):调用 dayjs().month() 同样返回 0 ~ 11,方便与原生逻辑或 Moment.js 生态无缝对齐,并支持传参用于设置月份。
  • 上层面向展示(Formatter):调用 dayjs().format('M') 直接输出自然月数字字符串("1" ~ "12");调用 dayjs().format('MM') 则直接输出两位数补零格式("01" ~ "12")。
原生JS与Day.js获取当前月份的代码对比
图 1:原生 Date 与 Day.js 月份索引及映射机制对比

二、获取当前月份的操作步骤与处理流水线

无论采用原生 JavaScript 还是 Day.js,在代码中从零开始提取并格式化当前月份,通常都需要经历相同的四个处理阶段。理清这四个阶段有助于排查补零失败或月份偏差问题:

  1. 时间实例化:调用原生构造函数 new Date() 或 Day.js 工厂函数 dayjs(),捕获当前运行时系统的本地时间快照。
  2. 提取并纠偏月份数值:原生方法调用 now.getMonth() + 1 抵消 0 索引偏移;Day.js 可直接利用 format('M') 或同样使用 month() + 1。
  3. 格式化与前导补零:若业务要求两位定长月份(如报表筛选、API 传参),原生语法需借助 String(...).padStart(2, '0');Day.js 则直接指定 'MM' 占位符。
  4. 结果输出与消费:将处理完成的数据传递至前端界面视图、状态管理器或后端请求体中。
原生JS与Day.js获取当前月份的代码对比
图 2:获取与处理月份的操作步骤与代码流水线

三、常见业务场景的代码实现对比

为了在具体开发中快速参考,我们针对前端与 Node.js 常见的三个典型需求场景,给出两者的完整示例代码与运行表现对比。

场景 1:获取自然月份数值(1 ~ 12)

当月份需要直接参与数字比较、日历算法或条件分支判断时,我们通常需要 number 类型的数值:

// 运行环境:浏览器控制台或 Node.js 环境

// --- 方式 A:原生 JavaScript ---
const nowDate = new Date();
const currentMonthNative = nowDate.getMonth() + 1;
console.log(currentMonthNative); 
// 示例输出:11 (类型:number)

// --- 方式 B:Day.js ---
import dayjs from 'dayjs';
const currentMonthDayjs = dayjs().month() + 1;
// 或者通过 Number(dayjs().format('M')) 转换
console.log(currentMonthDayjs); 
// 示例输出:11 (类型:number)

在这个场景下,原生 JavaScript 的写法最为轻量,执行性能最高,且不需要引入任何第三方包。

场景 2:获取两位数前导补零月份("01" ~ "12")

数据表格、导出文件名或日志打印往往需要两位对齐的月份格式:

// --- 方式 A:原生 JavaScript ---
const date = new Date();
const monthPadNative = String(date.getMonth() + 1).padStart(2, '0');
console.log(monthPadNative); 
// 示例输出:"11"(若当前是5月,则输出 "05";类型:string)

// --- 方式 B:Day.js ---
const monthPadDayjs = dayjs().format('MM');
console.log(monthPadDayjs); 
// 示例输出:"11"(若当前是5月,则输出 "05";类型:string)

差异解析:原生写法需要先后经过“取值”、“加一”、“类型强转为字符串”、“字符串左侧补零”四步操作;如果漏掉 String() 直接对数字调用 padStart(),运行时会直接抛出 TypeError: ... is not a function 错误。而 Day.js 的 format('MM') 属于声明式语法,语义一目了然,容错率极高。

场景 3:获取“年-月”一体化字符串("YYYY-MM")

在后端接口查询按月汇总的数据时,常见的入参格式为 "2026-11":

// --- 方式 A:原生 JavaScript ---
const targetDate = new Date();
const year = targetDate.getFullYear();
const month = String(targetDate.getMonth() + 1).padStart(2, '0');
const ymNative = `${year}-${month}`;
console.log(ymNative); 
// 示例输出:"2026-11"

// --- 方式 B:Day.js ---
const ymDayjs = dayjs().format('YYYY-MM');
console.log(ymDayjs); 
// 示例输出:"2026-11"

可以看到,随着输出格式复杂度的增加,原生写法的代码行数与临时变量显著增多,而 Day.js 依然能保持单行链式表达,后期若需变更为 "2026/11" 或 "2026年11月",仅需修改模板字符串即可。

原生JS与Day.js获取当前月份的代码对比
图 3:三种常见业务场景下的代码实现与表达力对照

四、容易忽略的边界与代码陷阱

在日常代码审查中,关于月份获取有以下三个典型陷阱需要特别关注:

陷阱 1:跨年与跨月边界下的原生 setMonth 副作用
原生 Date 对象是可变对象(Mutable)。如果你在当前日期是 31 号的实例上调用 date.setMonth(date.getMonth() + 1),当目标月份只有 30 天或 28 天时,原生对象会自动溢出并前进到下一个月,产生难以察觉的静默 Bug。而 Day.js 是不可变对象(Immutable),调用 dayjs().add(1, 'month') 不会改变原变量,且会自动校准月末天数。
陷阱 2:混淆 Day.js 的 format('M') 与 month()
部分开发者在使用 Day.js 时,误以为其封装的 dayjs().month() 会自动矫正为自然月,因而在业务逻辑中直接写出类似 if (dayjs().month() === 11) 的判断,导致该条件在实际 12 月才被触发。请牢记:.month() 始终返回 0~11,展示请优先使用 .format('M')。

五、选型建议与总结

为了帮助团队在实际技术栈中选择最合适的方案,下表对原生 JavaScript 与 Day.js 在获取与处理当前月份时的各维度特征进行了横向对比:

对比维度 原生 JavaScript (Date) Day.js 库
打包体积 0 KB(无需安装,全平台原生内置) 约 2 KB(轻量无依赖,Tree-shaking 友好)
获取自然月数值 new Date().getMonth() + 1 dayjs().month() + 1
两位数前导补零 需组合 String() 与 padStart() dayjs().format('MM') 声明式直出
年月复合输出 需多变量定义与模板字符串拼接 dayjs().format('YYYY-MM')
对象可变性 可变(容易产生副作用) 严格不可变(所有运算均返回新实例)
适用场景 极小脚本、性能敏感型算法、无构建工具页面 现代 Web 应用、管理后台、多格式展示与计算
原生JS与Day.js获取当前月份的代码对比
图 4:原生 JavaScript 与 Day.js 选型决策与核心维度总结

总结:如果你的项目只需要在极少数位置读取当前月份的数值用于简单计算,或者项目对第三方依赖体积有严苛限制(如基础 SDK、轻量级嵌入式脚本),直接使用 new Date().getMonth() + 1 是最直接高效的途径;而在大多数现代前端工程、数据后台或中大型项目中,日期处理通常伴随展示格式化、前导补零和范围运算,引入仅约 2KB 的 Day.js 能显著减少胶水代码,避免手写补零与索引纠偏带来的隐患,大幅提升代码的可读性与工程维护效率。

作者最新文章
相关文章
更多