工具函数参考
@jiess/utils 提供了 31 个以 $ 前缀命名的工具函数,按功能分为以下类别。
格式速查
日期格式码
| 码 | 含义 | 示例输出 |
|---|---|---|
yyyy / YYYY | 四位年份 | 2023 |
yy | 两位年份 | 23 |
MM | 月份(大写=月) | 01~12 |
dd / DD | 日期(大写/小写均可) | 01~31 |
HH | 24小时制(大写=时) | 00~23 |
hh | 12小时制(小写=时) | 01~12 |
mm | 分钟(小写=分) | 00~59 |
ss | 秒 | 00~59 |
SSS / S | 毫秒 | 000~999 |
qq | 季度 | 01~04 |
注意:
MM是月份,mm是分钟;HH是 24 小时制,hh是 12 小时制。yyyy和YYYY等效,dd和DD等效。
$check 支持的类型字符串
string, number, boolean, array, object, function, symbol, bigint, null, undefined, regexp/regex/exp, date, promise, error
一、类型判断
$check(value, type, state?)
精确的类型检查,同时作为 TypeScript 类型守卫。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
value | any | ✅ | 待检查的值 |
type | string | string[] | ✅ | 期望类型,大小写不敏感,支持数组 |
state | boolean | ❌ | 默认 true,false 时不抛异常,直接返回 false |
返回:boolean,同时触发 TypeScript 类型收窄。
// —— 基本用法 ——
$check('hello', 'string') // true
$check(123, 'number') // true
$check([], 'array') // true
$check(null, 'null') // true
// —— 类型守卫 ——
if ($check(value, 'string')) {
// 此处 TypeScript 自动将 value 收窄为 string
value.toUpperCase()
}
// —— 数组匹配(满足其一即可) ——
if ($check(value, ['string', 'number'])) {
// value 被收窄为 string | number
}
// —— 支持特殊类型 ——
$check(new Date(), 'Date') // true
$check(/regex/, 'exp') // true(大小写不敏感)
$check(Symbol('x'), 'Symbol') // true
$check(BigInt(1), 'BigInt') // true
// —— state 参数控制 ——
$check('hello', 123 as any, false) // false,不抛异常
$check('hello', 123 as any, true) // 抛出异常$identify(value, type, state?)
与 $check 完全相同(export const $identify = $check),两个名称可互换使用。
二、对象操作
$diff(a, b, isClone?)
深度比较两个值是否相等,正确处理循环引用。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
a | any | ✅ | 第一个待比较值 |
b | any | ✅ | 第二个待比较值 |
isClone | boolean | ❌ | 默认 true;false 时跳过克隆步骤直接深度比较(非浅引用比较) |
$diff({ a: 1, b: { c: 2 } }, { a: 1, b: { c: 2 } }) // true
$diff(1, '1') // false
$diff(NaN, NaN) // true(NaN 特殊处理)
// 循环引用
const a: any = {}, b: any = {}
a.self = a; b.self = b
$diff(a, b) // true支持的特殊类型:除普通对象/数组外,
$diff还能正确比较Date、RegExp、Map、Set、ArrayBuffer/SharedArrayBuffer、TypedArray、BigInt、Symbol、Function(按字符串形式比较)。Promise始终按引用判定(不同 Promise 实例即使内容相同也返回false)。
$clone(target, custom?, seen?)
深度克隆,支持循环引用、Symbol 键、Date/RegExp/BigInt。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
target | any | ✅ | 被克隆对象 |
custom | (val, type) => any | ❌ | 自定义处理回调;type 为 'filter' 时在克隆各属性值阶段调用(返回非 undefined 则替换该值,返回 undefined 则跳过该属性),type 为 'clone' 时在整棵树克隆完成后对结果调用(返回非 undefined 则替换最终结果) |
seen | WeakMap | ❌ | 内部使用,用于防止循环引用无限递归 |
const obj = { a: 1, b: { c: 2 } }
const cloned = $clone(obj)
cloned.b !== obj.b // 深克隆,内部引用不等
// 循环引用
const self: any = { a: 1 }
self.myself = self
const cl = $clone(self)
cl.myself === cl // true,循环关系被保持
// 自定义处理
const cl2 = $clone({ fn: () => {} }, (val, type) => {
return type === 'filter' && $check(val, 'function') ? '[函数]' : val
})
// cl2.fn === '[函数]'注意:带
JIESS_TAG标记的 Jiess 内部对象不会被深度克隆,而是传递引用。
$copy(obj_new, obj_old)
将旧对象的所有属性深度拷贝到新实例,用于从模板对象生成新对象。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
obj_new | object | ✅ | 新对象(就地修改) |
obj_old | object | ✅ | 旧对象 |
const template = { a: 1, b: { c: 2 } }
const instance = {}
$copy(instance, template)
// instance = { a: 1, b: { c: 2 } }
// instance.b !== template.b(深拷贝)与
$clone的区别:$clone返回新对象,$copy将旧属性写入已有对象。
$deepMerge(target, source)
深度合并,仅当 source 属性为"纯粹对象"时才递归合并,其他类型直接覆盖。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
target | object | ✅ | 目标对象(就地修改) |
source | object | ✅ | 源对象 |
const t = { a: 1, b: { x: 1 } }
$deepMerge(t, { b: { y: 2 }, c: 3 })
// t = { a: 1, b: { x: 1, y: 2 }, c: 3 }
// 数组:直接覆盖,不做合并
const t2 = { arr: [1, 2] }
$deepMerge(t2, { arr: [3, 4] })
// t2.arr = [3, 4](非合并结果)三、路径操作
$getByPath(obj, path)
按点分隔路径安全读取深层属性,路径不存在时返回 undefined 而非报错。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
obj | object | ✅ | 目标对象 |
path | string | (string|number)[] | ✅ | 'a.b.c'、'a[0].b' 或 ['a', 0, 'b'] |
const data = { user: { profile: { name: '张三' } } }
$getByPath(data, 'user.profile.name') // '张三'
$getByPath(data, ['user', 'profile', 'name']) // '张三'
$getByPath(data, 'user.profile.missing') // undefined(不报错)
$getByPath(data, '') // undefined(空路径返回 undefined)$setByPath(obj, path, value)
按路径写入值,中间的路径会自动创建对象/数组。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
obj | object | ✅ | 目标对象(就地修改) |
path | string | ✅ | 点分隔路径字符串 |
value | any | ✅ | 待写入值 |
const obj: any = {}
$setByPath(obj, 'a.b.c', 'hello')
// obj = { a: { b: { c: 'hello' } } }
// 数组索引格式:路径中 [n] 会被解析为数字索引,自动创建数组
$setByPath(obj, 'list[0].name', '张三')
// obj.list = [{ name: '张三' }]
// a[] 推送语法:路径以 [] 结尾时,将 value 追加到目标数组末尾(数组不存在则自动创建)
$setByPath(obj, 'tags[]', 'a')
$setByPath(obj, 'tags[]', 'b')
// obj.tags = ['a', 'b']四、日期与时间
$dateFormat(date, fmt)
将 Date 对象(或时间戳、日期字符串)按格式字符串输出。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
date | Date | number | string | ✅ | 日期数据 |
fmt | string | ✅ | 格式字符串(见 格式速查) |
const d = new Date('2023-06-15T14:30:45.123')
$dateFormat(d, 'yyyy-MM-dd') // '2023-06-15'
$dateFormat(d, 'yyyy-MM-dd HH:mm:ss') // '2023-06-15 14:30:45'
$dateFormat(d, 'yyyy年MM月dd日 HH时mm分ss秒') // '2023年06月15日 14时30分45秒'
$dateFormat(d, 'yyyy-MM-dd qq') // '2023-06-15 02'(Q2 季度)
$dateFormat(d, 'HH:mm:ss.SSS') // '14:30:45.123'
$dateFormat(d, '') // ''$timer(fn?, wait?)
一次性延迟执行的回调,执行后自动清除,无返回值、外部无法取消。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
fn | Function | ❌ | () => {} | 回调函数 |
wait | number | ❌ | 0 | 等待毫秒数 |
$timer(() => {
console.log('2秒后执行')
}, 2000)
// 2 秒后打印,无需手动 clearTimeout五、防抖与节流
工厂函数与实例函数
| 函数 | 模式 | 首次执行 | 说明 |
|---|---|---|---|
$debounce1(fn, wait) | 防抖 | 延迟 | 高频触发结束后等待 wait 再执行 |
$debounce2(fn, wait) | 防抖 | 延迟 | 同 $debounce1,始终清除旧计时器重新计时 |
$throttle1(fn, wait) | 节流-计时器 | 延迟 | 每隔 wait 执行一次,首次等待 wait 后执行 |
$throttle2(fn, wait) | 节流-时间戳 | 立即 | 每隔 wait 执行一次,首次立即执行 |
| 工厂 | 说明 |
|---|---|
$baseDebounce1(callback1?, immediate?) | 创建带预置回调的防抖工厂 |
$baseDebounce2(callback1?) | 同上,$debounce2 的工厂版本 |
$baseThrottle1(callback1?) | 创建带预置回调的节流工厂 |
$baseThrottle2(callback1?) | 同上,$throttle2 的工厂版本 |
// —— 搜索输入防抖 ——
const onInput = (val: string) => {
$debounce1(() => fetch(`/search?q=${val}`), 300)
}
// —— 滚动事件节流 ——
window.addEventListener('scroll', () => {
$throttle1(() => updateScrollUI(window.scrollY), 100)
})
// —— 防抖对比:$debounce1 vs $debounce2 ——
// 用户快速输入 "abc",300ms 间隔:
// $debounce1 → 执行 1 次(输入结束 300ms 后,同 $debounce2)
// $debounce2 → 执行 1 次(同 $debounce1,两者均延迟执行)
// 区别:$debounce1 的 $baseDebounce1 支持 immediate 参数,$debounce2 无此选项
// —— 节流对比:$throttle1 vs $throttle2 ——
// 快速连续触发 10 次,间隔 50ms,wait=100ms:
// $throttle1 → 执行多次(首次等待 100ms,之后每次间隔 100ms)
// $throttle2 → 执行多次(首次立即执行,之后每次间隔 100ms)$microDebounce(fn)
基于 Promise.resolve().then() 的微任务防抖。调用 $microDebounce() 返回一个防抖函数,同一个防抖实例在微任务队列中最多存在一个待执行函数。
const microDebounce = $microDebounce()
microDebounce(() => console.log('A'))
microDebounce(() => console.log('B')) // A 被 B 覆盖
// 当前事件循环结束后仅输出 "B"
// 每次调用 $microDebounce() 创建独立实例,彼此不共享 pending 状态六、Cookie 操作
$getCookie(name)
读取指定名称的 cookie,name 参数已做正则转义,可安全使用。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | ✅ | cookie 名称 |
DOM 不可用时返回 null,无需环境检测。
const token = $getCookie('auth_token')
if (token) {
fetch('/api/profile', { headers: { Authorization: `Bearer ${token}` } })
}$setCookie(name, value, Days?)
写入 cookie,value 自动 encodeURIComponent。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | string | ✅ | — | cookie 名称 |
value | string | ✅ | — | cookie 值(自动编码) |
Days | number | ❌ | 30 | 过期天数;0 = 当天过期(session);负数 = 立即过期 |
$setCookie('theme', 'dark') // 30 天后过期
$setCookie('token', jwt, 7) // 7 天后过期
$setCookie('temp', 'data', 0) // 会话级别
// 清除 cookie
$setCookie('old_key', '', -1)七、URL 参数
$querystring
提供 stringify 和 parse 两个方法。
// stringify(obj) → 对象 → 查询字符串
$querystring.stringify({ name: '张三', age: 30, tags: ['a', 'b'] })
// "name=张三&age=30&tags=a&tags=b"
// parse(str) → 查询字符串 → 对象
$querystring.parse('name=张三&age=30&tags=a&tags=b')
// { name: '张三', age: '30', tags: ['a', 'b'] }
// 同名 key 自动聚合成数组
// 高级用法:构建带参数的 API URL
function buildUrl(path: string, params: Record<string, unknown>) {
const qs = $querystring.stringify(params)
return qs ? `${path}?${qs}` : path
}
buildUrl('/api/users', { page: 1, size: 20 }) // "/api/users?page=1&size=20"八、其他工具
$getUUID(len?)
生成随机字符串(非加密安全,勿用于密码学场景)。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
len | number | ❌ | 32 | 返回长度。0 返回空字符串 |
$getUUID() // 32 位随机字符串:"a1b2c3d4..."
$getUUID(8) // 8 位随机字符串$isDef(value) / $isUndef(value, b?)
判断值是否"有定义" / "无定义"。默认仅 null、undefined、NaN 视为无定义;b=true 时额外将空字符串 "" 也视为无定义。
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
value | any | ✅ | — | 被检查的值 |
b | boolean | ❌ | — | 为 true 时将空字符串也视为无定义 |
$isUndef(null) // true
$isUndef(undefined) // true
$isUndef(NaN) // true
$isUndef(0) // false(0 也算是"有定义"的值)
$isUndef('') // false(默认空字符串视为有定义)
$isUndef('', true) // true(b=true 时空字符串也视为无定义)
$isDef('hello') // true
$isDef(null) // false$firstUpperCase(str) / $firstLowerCase(str)
只转换首字母的大小写,其余字符不变。前导空白会被保留;非字符串类型原样返回;空字符串返回空字符串。
$firstUpperCase('hello') // 'Hello'
$firstLowerCase('Hello') // 'hello'
$firstUpperCase('') // ''
$firstUpperCase(' a') // ' A'(前导空白保留)
$firstUpperCase(123) // 123(非字符串原样返回)$nfn(..._)
空操作函数,用作默认回调占位符。接收任意参数,无返回值。
const options = {
onSuccess: userCallback || $nfn,
onError: errorCallback || $nfn
}$initExecute(ctx, ...args1)
返回一个执行器函数,可用于延迟调用。返回的执行器每次被调用时都会执行传入的 func,不做结果缓存。
// 返回的执行器可以多次调用不同的 func
const exec = $initExecute('prefix')
exec((prefix, extra) => `${prefix}_${extra}`, ['suffix'])
// 'prefix_suffix'(不缓存,每次调用都重新执行)
### `$canUseDom`
编译时常量 `boolean`,判断是否处于浏览器环境(`window` 和 `document` 是否可用)。
```typescript
if ($canUseDom) {
// 安全操作 DOM
document.addEventListener('DOMContentLoaded', init)
} else {
// SSR / Node.js 环境
}$serializeObject(obj)
对象序列化,支持 Jiess 内部对象类型(Date、RegExp、Map、Set、模板对象等)的特殊处理。
| 值类型 | 序列化结果 |
|---|---|
| Date | 'Date: ISO字符串' |
| RegExp | 'RegExp: /pattern/flags' |
| Map | 'Map: [[k,v],...]' |
| Set | 'Set: [v,...]' |
模板对象($model=template) | 'Template: name' 或 JSON |
| 普通对象 | 紧凑 JSON |
边界情况速查
| 函数 | 边界行为 |
|---|---|
$diff | NaN === NaN → true;isClone=false 时跳过克隆但仍为深度比较;isClone=true 时带 JIESS_TAG/isNotClone 标记的对象不克隆、传递引用参与比较 |
$clone | 带 JIESS_TAG 的内部对象传递引用;seen WeakMap 防递归 |
$deepMerge | 数组和特殊对象直接替换,不做合并;undefined 值会覆盖 target |
$check | 'array' 用 Array.isArray;type 为数组时批量匹配 |
$dateFormat | 无效格式中的字符 d 会被日期值替换(如 'invalid' → 'invali1') |
$getUUID | 基于 Math.random(),非加密安全,勿用于 token 生成 |
$microDebounce | 返回 Promise,但无 async 标记时返回值是同步链 |
$getByPath | path='' 返回 undefined(而非 obj 自身);多段中间为 undefined 时整体返回 undefined |
$setByPath | 中间路径自动创建,数组索引需用数字 |
$timer | 内部 clearTimeout,外部无法取消 |