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

相关推荐
灵感__idea7 小时前
Hello 算法:贪心的世界
前端·javascript·算法
killerbasd10 小时前
牧苏苏传 我不装了 4/7
前端·javascript·vue.js
橘子编程11 小时前
JavaScript与TypeScript终极指南
javascript·ubuntu·typescript
叫我一声阿雷吧12 小时前
JS 入门通关手册(45):浏览器渲染原理与重绘重排(性能优化核心,面试必考
javascript·前端面试·前端性能优化·浏览器渲染·浏览器渲染原理,重排重绘·reflow·repaint
大家的林语冰12 小时前
《前端周刊》尤大开源 Vite+ 全家桶,前端工业革命启动;尤大爆料 Void 云服务新产品,Vite 进军全栈开发;ECMA 源码映射规范......
前端·javascript·vue.js
jiayong2312 小时前
第 8 课:开始引入组合式函数
前端·javascript·学习
天若有情67313 小时前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
yuki_uix14 小时前
重排、重绘与合成——浏览器渲染性能的底层逻辑
前端·javascript·面试
止观止14 小时前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext
时寒的笔记14 小时前
js逆向7_案例惠nong网
android·开发语言·javascript