某些封装的函数,其参数具有多样性,会导致函数中会增加非常多的分支,比如下面这个 format
函数有如下几种参数方式,其中 formatter 会有很多种情况
- date:日期对象
- formatter:
- ‘date’:格式化日期
- ‘datetime’:带有时间
- 可自定义返回格式
- 自行处理的函数
- isPad:是否补零
function format(date, formatter, isPad = false) {
...
}
// 2024-9-29
format(new Date(), 'date')
// 2024-9-29 7:3:10
format(new Date(), 'datetime')
// 2024-09-29
format(new Date(), 'date', true)
// 2024-09-29 07:03:10
format(new Date(), 'datetime', true)
// 2024年09月29日 07:03:10
format(new Date(), 'yyyy年MM月dd日 HH:mm:ss.ms ', true)
// 2024年9月29日 7:3:10
format(new Date('2012-12-31'), (dateInfo => {
const {
year } = dateInfo
const thisYear = new Date().getFullYear()
if (year < thisYear) {
return `${
thisYear - year}年前`
} else if (year > thisYear) {
return `${
year - thisYear}年后`
} else {
return '今年'
}
}))
可以通过 参数归一化,选择一种能涵盖其他情况的参数,在本例中选择功能最灵活且强大的函数类型参数
封装辅助函数,返回归一化的结果(函数)
function _formatNormalize(formatter){
if(typeof formatter === 'function'){
return formatter
}
if(typeof formatter !== 'string'){
throw new TypeError('参数类型必须为字符串或函数')
}
return ()=>{
...}
}
function format(date, formatter, isPad = false) {
formatter = _formatNormalize(formatter)
formatter()
}
处理完 函数 和 非字符串 类型,继续分析 字符串类型 参数,它可能为 date、datetime以及模版字符串三种形式,挑选出其中功能最强大的方式:模版字符串,然后使用模版字符串替代date、和datetime的情况。
function _formatNormalize(formatter) {
if (typeof formatter === 'function') {
return formatter
}
if (typeof formatter !== 'string') {
throw new TypeError('参数类型必须为字符串或函数')
}
if (formatter === 'date') {
formatter = 'yyyy-MM-dd'
}
else if (formatter === 'datetime') {
formatter = 'yyyy-MM-dd HH:mm:ss'
}
return (dateInfo) => {
const {
year, month, day, hour, minute, second, millisecond } = dateInfo
return formatter.replace('yyyy', year)
.replace('MM', month)
.replace('dd', day)
.replace('HH', hour)
.replace('mm', minute)
.replace('ss', second)
.replace('ms', millisecond)
}
}
将参数的多样性选择抽离到辅助函数中,实现对 formatter参数 归一化
function formate(date, formatter, isPad = false) {
formatter = _formatNormalize(formatter)
const dateInfo = {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hour: date.getHours(),
minute: date.getMinutes(),
second: date.getSeconds(),
millisecond: date.getMilliseconds(),
}
if (isPad) {
dateInfo.year = dateInfo.year.toString().padStart(4, '0')
dateInfo.month = dateInfo.month.toString().padStart(2, '0')
dateInfo.day = dateInfo.day.toString().padStart(2, '0')
dateInfo.hour = dateInfo.hour.toString().padStart(2, '0')
dateInfo.minute = dateInfo.minute.toString().padStart(2, '0')
dateInfo.second = dateInfo.second.toString().padStart(2, '0')
dateInfo.millisecond = dateInfo.millisecond.toString().padStart(3, '0')
}
return formatter(dateInfo)
}