Day.js 源码深度剖析:极简时间库的设计艺术

Day.js 源码深度剖析:极简时间库的设计艺术

1. 项目背景与构建流程

Day.js (v1.11.20) 是一个轻量级的 JavaScript 时间处理库,其 API 设计高度兼容 Moment.js。 通过分析 package.json 可知,该项目使用 Rollup 作为构建工具,通过"编译、打包、压缩"三部曲生成最终的 dayjs.min.js,而这一切的核心入口正是 src/index.js

2 多级缓存策略

Day.js 通过两级缓存机制实现高效的日期操作和格式化。

2.1全局 Locale 缓存

Ls 对象用于缓存已加载的语言包,避免重复加载和解析:

javascript 复制代码
let L = 'en' // global locale
const Ls = {} // global loaded locale

const parseLocale = (preset, object, isLocal) => {
  let l
  if (!preset) return L
  if (typeof preset === 'string') {
    const presetLower = preset.toLowerCase()
    if (Ls[presetLower]) {
      l = presetLower
    }
    if (object) {
      Ls[presetLower] = object
      l = presetLower
    }
    const presetSplit = preset.split('-')
    if (!l && presetSplit.length > 1) {
      return parseLocale(presetSplit[0])
    }
  } else {
    const { name } = preset
    Ls[name] = preset
    l = name
  }
  if (!isLocal && l) L = l
  return l || (!isLocal && L)
}

2.2数据缓存与初始化

Day.js 在实例化时会调用 init() 方法,将日期对象的各项数值解构并缓存到实例属性中,从而实现高效的格式化输出。

javascript 复制代码
init() {
  const { $d } = this
  this.$y = $d.getFullYear()
  this.$M = $d.getMonth()
  this.$D = $d.getDate()
  this.$W = $d.getDay()
  this.$H = $d.getHours()
  this.$m = $d.getMinutes()
  this.$s = $d.getSeconds()
  this.$ms = $d.getMilliseconds()
}

3. 灵活的插件系统

Day.js 的核心非常精简,复杂功能主要通过 extend 静态方法注入。

3.1 dayjs.extend 实现原理

插件接受三个参数:配置选项 option、类引用 Dayjs 和工厂函数 dayjs

javascript 复制代码
dayjs.extend = (plugin, option) => {
  if (!plugin.$i) { // 确保插件只安装一次
    plugin(option, Dayjs, dayjs)
    plugin.$i = true
  }
  return dayjs
}

3.2 插件开发示例:isToday

我们可以通过扩展 Dayjs.prototype 轻松实现自定义功能:

javascript 复制代码
const myPlugin = (o, c, d) => {
  const proto = c.prototype
  proto.isToday = function () {
    const comparisonTemplate = 'YYYY-MM-DD'
    const now = d()
    return this.format(comparisonTemplate) === now.format(comparisonTemplate)
  }
}

// 使用插件
dayjs.extend(myPlugin)
dayjs().isToday()        // true/false
dayjs('2024-03-20').isToday()

3.3内置插件使用

javascript 复制代码
import advancedFormat from 'dayjs/plugin/advancedFormat' // load on demand

dayjs.extend(advancedFormat) // use plugin

dayjs().format('Q Do k kk X x') // more available formats

4. 国际化 (i18n) 设计

Day.js 提供了极其详尽的本地化配置,支持日期格式化模版、相对时间描述及复杂的时间段判断。

javascript 复制代码
const locale = {
  name: 'zh-cn',
  weekdays: '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
  months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
  // ... 其他配置
  meridiem: (hour, minute) => {
    const hm = (hour * 100) + minute
    if (hm < 600) return '凌晨'
    else if (hm < 900) return '早上'
    else if (hm < 1100) return '上午'
    else if (hm < 1300) return '中午'
    else if (hm < 1800) return '下午'
    return '晚上'
  }
}

5. 总结

Day.js 通过严谨的依赖管理、高效的属性缓存以及极具扩展性的插件系统,完美平衡了"轻量级"与"功能性"。它是现代前端开发中处理时间数据的首选库之一。

相关推荐
清风徐来QCQ2 小时前
js中的模板字符串
开发语言·前端·javascript
SuperEugene3 小时前
Vue3 + Element Plus 表格实战:批量操作、行内编辑、跨页选中逻辑统一|表单与表格规范篇
开发语言·前端·javascript
极梦网络无忧3 小时前
基于 Vite + Vue3 的组件自动注册功能
前端·javascript·vue.js
软弹4 小时前
深入理解 React Ref 机制:useRef 与 forwardRef 的协作原理
前端·javascript·react.js
雪碧聊技术4 小时前
前端vue代码架子搭建
前端·javascript·vue.js·前端项目代码框架搭建
han_4 小时前
JavaScript设计模式(二):策略模式实现与应用
前端·javascript·设计模式
x***r1514 小时前
Notepad++ 8.6 安装教程:详细步骤+自定义安装路径(附注意事项)
linux·前端·javascript
Hilaku4 小时前
为什么很多工作 5 年的前端,身价反而卡住了?🤷‍♂️
前端·javascript·面试
执行部之龙4 小时前
JS手写——call bind apply
前端·javascript