pen-it 1.0.6 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4,11 +4,6 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
4
  * 判断一个值是否为数组
5
5
  * @param value - 要判断的值
6
6
  * @returns 如果是数组返回 true,否则返回 false
7
- * @example
8
- * isArray([1, 2, 3])
9
- * // => true
10
- * isArray("hello")
11
- * // => false
12
7
  */
13
8
  const isArray = (value) => {
14
9
  return Array.isArray(value);
@@ -17,11 +12,6 @@ const isArray = (value) => {
17
12
  * 判断一个值是否为对象(但不是数组)
18
13
  * @param value - 要判断的值
19
14
  * @returns 如果是对象且不是数组返回 true,否则返回 false
20
- * @example
21
- * isObject({ a: 1 })
22
- * // => true
23
- * isObject([1, 2])
24
- * // => false
25
15
  */
26
16
  const isObject = (value) => {
27
17
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -31,9 +21,6 @@ const isObject = (value) => {
31
21
  * @param val - 要判断的数据
32
22
  * @param type - 数据类型字符串,如 "Array"、"Function"
33
23
  * @returns 如果数据是指定类型返回 true
34
- * @example
35
- * is([], "Array")
36
- * // => true
37
24
  */
38
25
  const is = (val, type) => {
39
26
  return Object.prototype.toString.call(val) === `[object ${type}]`;
@@ -42,9 +29,6 @@ const is = (val, type) => {
42
29
  * 判断一个值是否为函数
43
30
  * @param val - 要判断的数据
44
31
  * @returns 如果是函数返回 true
45
- * @example
46
- * isFunction(() => {})
47
- * // => true
48
32
  */
49
33
  const isFunction = (val) => {
50
34
  return is(val, "Function") || !!(val && val.constructor && val.call && val.apply);
@@ -53,9 +37,6 @@ const isFunction = (val) => {
53
37
  * 判断一个值是否为 Date 对象
54
38
  * @param val - 要判断的数据
55
39
  * @returns 如果是 Date 对象返回 true
56
- * @example
57
- * isDate(new Date())
58
- * // => true
59
40
  */
60
41
  const isDate = (val) => {
61
42
  return is(val, "Date") || !!val && val.constructor === Date;
@@ -64,11 +45,6 @@ const isDate = (val) => {
64
45
  * 判断一个值是否为数字(NaN 和 Infinity 也视为数字)
65
46
  * @param val - 要判断的数据
66
47
  * @returns 如果是数字返回 true
67
- * @example
68
- * isNumber(42)
69
- * // => true
70
- * isNumber("42")
71
- * // => false
72
48
  */
73
49
  const isNumber = (val) => {
74
50
  return Number(val) === val;
@@ -77,11 +53,6 @@ const isNumber = (val) => {
77
53
  * 判断一个值是否为整数
78
54
  * @param val - 要判断的数据
79
55
  * @returns 如果是整数返回 true
80
- * @example
81
- * isInt(42)
82
- * // => true
83
- * isInt(3.14)
84
- * // => false
85
56
  */
86
57
  const isInt = (val) => {
87
58
  return isNumber(val) && Number.isFinite(val) && val % 1 === 0;
@@ -90,11 +61,6 @@ const isInt = (val) => {
90
61
  * 判断一个值是否为浮点数(有限小数)
91
62
  * @param val - 要判断的数据
92
63
  * @returns 如果是浮点数返回 true
93
- * @example
94
- * isFloat(3.14)
95
- * // => true
96
- * isFloat(42)
97
- * // => false
98
64
  */
99
65
  const isFloat = (val) => {
100
66
  return isNumber(val) && Number.isFinite(val) && val % 1 !== 0;
@@ -103,9 +69,6 @@ const isFloat = (val) => {
103
69
  * 判断一个值是否为异步函数
104
70
  * @param val - 要判断的数据
105
71
  * @returns 如果是异步函数返回 true
106
- * @example
107
- * isAsyncFunction(async () => {})
108
- * // => true
109
72
  */
110
73
  const isAsyncFunction = (val) => {
111
74
  return is(val, "AsyncFunction");
@@ -114,9 +77,6 @@ const isAsyncFunction = (val) => {
114
77
  * 判断一个值是否为 Promise
115
78
  * @param value - 要判断的数据
116
79
  * @returns 如果是 Promise 返回 true
117
- * @example
118
- * isPromise(Promise.resolve())
119
- * // => true
120
80
  */
121
81
  const isPromise = (value) => {
122
82
  if (!value) return false;
@@ -128,11 +88,6 @@ const isPromise = (value) => {
128
88
  * 判断一个值是否为字符串
129
89
  * @param val - 要判断的数据
130
90
  * @returns 如果是字符串返回 true
131
- * @example
132
- * isString("hello")
133
- * // => true
134
- * isString(42)
135
- * // => false
136
91
  */
137
92
  const isString = (val) => {
138
93
  return is(val, "String") || typeof val === "string" || val instanceof String;
@@ -141,11 +96,6 @@ const isString = (val) => {
141
96
  * 判断一个值是否为布尔值
142
97
  * @param val - 要判断的数据
143
98
  * @returns 如果是布尔值返回 true
144
- * @example
145
- * isBoolean(true)
146
- * // => true
147
- * isBoolean(1)
148
- * // => false
149
99
  */
150
100
  const isBoolean = (val) => {
151
101
  return typeof val === "boolean" || is(val, "Boolean");
@@ -153,9 +103,6 @@ const isBoolean = (val) => {
153
103
  /**
154
104
  * 判断是否为 PC 端(浏览器环境)
155
105
  * @returns 如果在浏览器环境中返回 true
156
- * @example
157
- * isPC()
158
- * // => true(在浏览器中)
159
106
  */
160
107
  const isPC = () => {
161
108
  return typeof window !== "undefined";
@@ -164,9 +111,6 @@ const isPC = () => {
164
111
  * 判断一个值是否为 window 对象
165
112
  * @param val - 要判断的数据
166
113
  * @returns 如果是 window 对象返回 true
167
- * @example
168
- * isWindow(window)
169
- * // => true(在浏览器中)
170
114
  */
171
115
  const isWindow = (val) => {
172
116
  return typeof window !== "undefined" && is(val, "Window");
@@ -175,9 +119,6 @@ const isWindow = (val) => {
175
119
  * 判断一个值是否为 DOM 元素
176
120
  * @param val - 要判断的数据
177
121
  * @returns 如果是 DOM 元素返回 true
178
- * @example
179
- * isElement(document.body)
180
- * // => true
181
122
  */
182
123
  const isElement = (val) => {
183
124
  return isObject(val) && !!val.tagName;
@@ -186,9 +127,6 @@ const isElement = (val) => {
186
127
  * 判断一个值是否为 null
187
128
  * @param val - 要判断的数据
188
129
  * @returns 如果是 null 返回 true
189
- * @example
190
- * isNull(null)
191
- * // => true
192
130
  */
193
131
  const isNull = (val) => {
194
132
  return val === null;
@@ -197,11 +135,6 @@ const isNull = (val) => {
197
135
  * 判断一个值是否为十六进制颜色
198
136
  * @param str - 要判断的字符串
199
137
  * @returns 如果是有效的十六进制颜色值返回 true
200
- * @example
201
- * isHexColor("#fff")
202
- * // => true
203
- * isHexColor("#ff0000")
204
- * // => true
205
138
  */
206
139
  const isHexColor = (str) => {
207
140
  return /^#?([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/.test(str);
@@ -209,9 +142,6 @@ const isHexColor = (str) => {
209
142
  /**
210
143
  * 判断设备是否为 iOS
211
144
  * @returns 如果是 iOS 设备返回 true
212
- * @example
213
- * isIOS()
214
- * // => true(在 iPhone/iPad 上)
215
145
  */
216
146
  const isIOS = () => {
217
147
  return /iPad|iPhone|iPod/.test(navigator.userAgent);
@@ -220,9 +150,6 @@ const isIOS = () => {
220
150
  * 判断一个值是否为有效的电子邮件
221
151
  * @param email - 要判断的字符串
222
152
  * @returns 如果是有效的电子邮件地址返回 true
223
- * @example
224
- * isValidEmail("test@example.com")
225
- * // => true
226
153
  */
227
154
  const isValidEmail = (email) => {
228
155
  return /^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/.test(email);
@@ -231,11 +158,6 @@ const isValidEmail = (email) => {
231
158
  * 判断一个值是否已定义(不是 undefined)
232
159
  * @param val - 要判断的数据
233
160
  * @returns 如果不是 undefined 返回 true
234
- * @example
235
- * isDef("hello")
236
- * // => true
237
- * isDef(undefined)
238
- * // => false
239
161
  */
240
162
  const isDef = (val) => {
241
163
  return typeof val !== "undefined";
@@ -244,9 +166,6 @@ const isDef = (val) => {
244
166
  * 判断一个值是否为 undefined
245
167
  * @param val - 要判断的数据
246
168
  * @returns 如果是 undefined 返回 true
247
- * @example
248
- * isUnDef(undefined)
249
- * // => true
250
169
  */
251
170
  const isUnDef = (val) => {
252
171
  return typeof val === "undefined";
@@ -255,13 +174,6 @@ const isUnDef = (val) => {
255
174
  * 判断一个值是否为 null 或 undefined
256
175
  * @param val - 要判断的数据
257
176
  * @returns 如果是 null 或 undefined 返回 true
258
- * @example
259
- * isNullOrUnDef(null)
260
- * // => true
261
- * isNullOrUnDef(undefined)
262
- * // => true
263
- * isNullOrUnDef("hello")
264
- * // => false
265
177
  */
266
178
  const isNullOrUnDef = (val) => {
267
179
  return isUnDef(val) || isNull(val);
@@ -270,9 +182,6 @@ const isNullOrUnDef = (val) => {
270
182
  * 判断一个值是否为 symbol
271
183
  * @param value - 要判断的数据
272
184
  * @returns 如果是 symbol 返回 true
273
- * @example
274
- * isSymbol(Symbol("foo"))
275
- * // => true
276
185
  */
277
186
  const isSymbol = (value) => {
278
187
  return !!value && value.constructor === Symbol;
@@ -282,11 +191,6 @@ const isSymbol = (value) => {
282
191
  * 原始类型包括:number、string、boolean、symbol、bigint、undefined、null
283
192
  * @param value - 要判断的值
284
193
  * @returns 如果是原始类型返回 true
285
- * @example
286
- * isPrimitive(42)
287
- * // => true
288
- * isPrimitive({})
289
- * // => false
290
194
  */
291
195
  const isPrimitive = (value) => {
292
196
  return value === void 0 || value === null || typeof value !== "object" && typeof value !== "function";
@@ -296,13 +200,6 @@ const isPrimitive = (value) => {
296
200
  * 空值包括:null、undefined、空字符串、空数组、空对象、空 Map/Set、无效 Date
297
201
  * @param value - 要判断的数据
298
202
  * @returns 如果为空返回 true
299
- * @example
300
- * isEmpty("")
301
- * // => true
302
- * isEmpty([])
303
- * // => true
304
- * isEmpty(0)
305
- * // => false
306
203
  */
307
204
  const isEmpty = (value) => {
308
205
  if (value === null || value === void 0) return true;
@@ -320,19 +217,6 @@ const isEmpty = (value) => {
320
217
  * 支持:字符串、数组、对象、Map、Set、类型化数组
321
218
  * @param value - 要检查的值
322
219
  * @returns 如果为空返回 true
323
- * @example
324
- * isEmptySv("")
325
- * // => true
326
- * isEmptySv(null)
327
- * // => true
328
- * isEmptySv([])
329
- * // => true
330
- * isEmptySv({})
331
- * // => true
332
- * isEmptySv(new Set())
333
- * // => true
334
- * isEmptySv(new Map())
335
- * // => true
336
220
  */
337
221
  function isEmptySv(value) {
338
222
  if (value === null || value === void 0) return true;
@@ -347,11 +231,6 @@ function isEmptySv(value) {
347
231
  * @param x - 要比较的第一个值
348
232
  * @param y - 要比较的第二个值
349
233
  * @returns 如果值深度相等返回 true
350
- * @example
351
- * isEqual({ a: 1 }, { a: 1 })
352
- * // => true
353
- * isEqual({ a: 1 }, { a: 2 })
354
- * // => false
355
234
  */
356
235
  const isEqual = (x, y) => {
357
236
  if (Object.is(x, y)) return true;
@@ -373,9 +252,6 @@ const isEqual = (x, y) => {
373
252
  * 完整日期时间(年/月/日 时分秒)_ 斜杠
374
253
  * @param date - Date 对象
375
254
  * @returns 格式化后的完整日期时间字符串,如 "2026/06/03 14:30:45"
376
- * @example
377
- * formatFull(new Date("2026-06-03T14:30:45"))
378
- * // => "2026/06/03 14:30:45"
379
255
  */
380
256
  const formatFull = (date) => {
381
257
  return new Intl.DateTimeFormat("zh-CN", {
@@ -392,9 +268,6 @@ const formatFull = (date) => {
392
268
  * 完整日期时间(年-月-日 时分秒)_ 短横线
393
269
  * @param date - Date 对象
394
270
  * @returns 格式化后的完整日期时间字符串,如 "2026-06-03 14:30:45"
395
- * @example
396
- * formatFullReplace(new Date("2026-06-03T14:30:45"))
397
- * // => "2026-06-03 14:30:45"
398
271
  */
399
272
  const formatFullReplace = (date) => {
400
273
  return formatFull(date).replace(/\//g, "-");
@@ -403,9 +276,6 @@ const formatFullReplace = (date) => {
403
276
  * 中文年月日
404
277
  * @param date - Date 对象
405
278
  * @returns 格式化后的中文日期字符串,如 "2026年6月3日"
406
- * @example
407
- * formatYMD(new Date("2026-06-03"))
408
- * // => "2026年6月3日"
409
279
  */
410
280
  const formatYMD = (date) => {
411
281
  return new Intl.DateTimeFormat("zh-CN", {
@@ -418,9 +288,6 @@ const formatYMD = (date) => {
418
288
  * 星期几
419
289
  * @param date - Date 对象
420
290
  * @returns 中文星期字符串,如 "星期三"
421
- * @example
422
- * formatWeek(new Date("2026-06-03"))
423
- * // => "星期三"
424
291
  */
425
292
  const formatWeek = (date) => {
426
293
  return new Intl.DateTimeFormat("zh-CN", { weekday: "long" }).format(date);
@@ -430,9 +297,6 @@ const formatWeek = (date) => {
430
297
  * @param value - 数值
431
298
  * @param options - 格式化选项
432
299
  * @returns 格式化后的货币字符串
433
- * @example
434
- * formatRmb(1234.56, { type: "zh-CN", currency: "CNY" })
435
- * // => "¥1,234.56"
436
300
  */
437
301
  const formatRmb = (value, options) => {
438
302
  return new Intl.NumberFormat(options.type, {
@@ -444,9 +308,6 @@ const formatRmb = (value, options) => {
444
308
  * 千位分隔符(数字格式化),中文(逗号分隔)
445
309
  * @param value - 数值
446
310
  * @returns 格式化后的千位分隔数字字符串
447
- * @example
448
- * formatNum(1234567)
449
- * // => "1,234,567"
450
311
  */
451
312
  const formatNum = (value) => {
452
313
  return new Intl.NumberFormat("zh-CN").format(value);
@@ -456,9 +317,6 @@ const formatNum = (value) => {
456
317
  * @param value - 百分比数值
457
318
  * @param digit - 保留的小数位数,默认为 0
458
319
  * @returns 格式化后的百分比字符串
459
- * @example
460
- * percentCN(0.1234, 2)
461
- * // => "12.34%"
462
320
  */
463
321
  const percentCN = (value, digit = 0) => {
464
322
  return new Intl.NumberFormat("zh-CN", {
@@ -470,9 +328,6 @@ const percentCN = (value, digit = 0) => {
470
328
  * 紧凑计数法(大数简化)_ 英文缩写
471
329
  * @param value - 数值
472
330
  * @returns 格式化后的紧凑数字字符串(英文缩写)
473
- * @example
474
- * compactEN(12345)
475
- * // => "12K"
476
331
  */
477
332
  const compactEN = (value) => {
478
333
  return new Intl.NumberFormat("en-US", {
@@ -484,9 +339,6 @@ const compactEN = (value) => {
484
339
  * 紧凑计数法(大数简化)_ 中文缩写
485
340
  * @param value - 数值
486
341
  * @returns 格式化后的紧凑数字字符串(中文缩写)
487
- * @example
488
- * compactCN(12345)
489
- * // => "1.2万"
490
342
  */
491
343
  const compactCN = (value) => {
492
344
  return new Intl.NumberFormat("zh-CN", {
@@ -499,12 +351,6 @@ const compactCN = (value) => {
499
351
  * @param value - 数值
500
352
  * @param digit - 保留的小数位数,默认为 0
501
353
  * @returns 格式化后的带正负号的数值显示
502
- * @example
503
- * signed(42, 1)
504
- * // => "+42.0"
505
- * @example
506
- * signed(-5)
507
- * // => "-5"
508
354
  */
509
355
  const signed = (value, digit = 0) => {
510
356
  return new Intl.NumberFormat("en-US", {
@@ -516,9 +362,6 @@ const signed = (value, digit = 0) => {
516
362
  * 手机号格式化脱敏 _ 隐藏中间 4 位数
517
363
  * @param phone - 手机号码
518
364
  * @returns 手机号格式化脱敏后的手机号
519
- * @example
520
- * maskPhone("13812345678")
521
- * // => "138****5678"
522
365
  */
523
366
  const maskPhone = (phone) => {
524
367
  return phone.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2");
@@ -527,9 +370,6 @@ const maskPhone = (phone) => {
527
370
  * 手机号格式化 _ 空格分隔
528
371
  * @param phone - 手机号
529
372
  * @returns 手机号空格格式化的手机号
530
- * @example
531
- * spacePhone("13812345678")
532
- * // => "138 1234 5678"
533
373
  */
534
374
  const spacePhone = (phone) => {
535
375
  return phone.replace(/(\d{3})(\d{4})(\d{4})/, "$1 $2 $3");
@@ -538,9 +378,6 @@ const spacePhone = (phone) => {
538
378
  * 每个单词首字母大写
539
379
  * @param str - 字符串
540
380
  * @returns 每个单词首字母大写后的字符串
541
- * @example
542
- * capitalize("hello world")
543
- * // => "Hello World"
544
381
  */
545
382
  const capitalize = (str) => {
546
383
  return str.replace(/\b\w/g, (char) => char.toUpperCase());
@@ -549,9 +386,6 @@ const capitalize = (str) => {
549
386
  * 短横线连接转小驼峰(kebab-case → camelCase)
550
387
  * @param str - 字符串
551
388
  * @returns 转换后的小驼峰字符串
552
- * @example
553
- * kebabToCamel("hello-world")
554
- * // => "helloWorld"
555
389
  */
556
390
  const kebabToCamel = (str) => {
557
391
  return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
@@ -560,9 +394,6 @@ const kebabToCamel = (str) => {
560
394
  * 大驼峰或小驼峰 _ 转为 ‘-’ 短横线连接
561
395
  * @param str - 字符串
562
396
  * @returns 大驼峰或小驼峰命名格式化的字符串
563
- * @example
564
- * camelToKebab("helloWorld")
565
- * // => "hello-world"
566
397
  */
567
398
  const camelToKebab = (str) => {
568
399
  return str.replace(/([A-Z])/g, "-$1").toLowerCase();
@@ -573,9 +404,6 @@ const camelToKebab = (str) => {
573
404
  * @param maxLength - 截断位置
574
405
  * @param suffix - 自定义的替换截断后的内容
575
406
  * @returns 超长文本截断后内容
576
- * @example
577
- * truncate("Hello World", 8)
578
- * // => "Hello..."
579
407
  */
580
408
  const truncate = (str, maxLength, suffix = "...") => {
581
409
  if (str.length <= maxLength) return str;
@@ -587,9 +415,6 @@ const truncate = (str, maxLength, suffix = "...") => {
587
415
  * @param maxWords - 截断位置
588
416
  * @param suffix - 自定义的替换截断后的内容
589
417
  * @returns 超长文本截断后内容
590
- * @example
591
- * truncateByWords("你好世界欢迎你", 4)
592
- * // => "你好世界..."
593
418
  */
594
419
  const truncateByWords = (str, maxWords, suffix = "...") => {
595
420
  const chars = str.split("");
@@ -600,18 +425,12 @@ const truncateByWords = (str, maxWords, suffix = "...") => {
600
425
  * 去除所有空格 _ 前后中间
601
426
  * @param str - 内容
602
427
  * @returns 去除空格后的内容
603
- * @example
604
- * trimAll(" hello world ")
605
- * // => "helloworld"
606
428
  */
607
429
  const trimAll = (str) => str.replace(/\s+/g, "");
608
430
  /**
609
431
  * 下划线转驼峰(snake_case → camelCase)
610
432
  * @param str - 字符串
611
433
  * @returns 转换后的驼峰字符串
612
- * @example
613
- * toCamel("hello_world")
614
- * // => "helloWorld"
615
434
  */
616
435
  const toCamel = (str) => {
617
436
  return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
@@ -620,9 +439,6 @@ const toCamel = (str) => {
620
439
  * 首字母大写
621
440
  * @param str - 字符串
622
441
  * @returns 首字母大写后的字符串
623
- * @example
624
- * firstUpper("hello")
625
- * // => "Hello"
626
442
  */
627
443
  const firstUpper = (str) => {
628
444
  return str.charAt(0).toUpperCase() + str.slice(1);
@@ -631,9 +447,6 @@ const firstUpper = (str) => {
631
447
  * 首字母小写
632
448
  * @param str - 字符串
633
449
  * @returns 首字母小写后的字符串
634
- * @example
635
- * firstLower("Hello")
636
- * // => "hello"
637
450
  */
638
451
  const firstLower = (str) => {
639
452
  return str.charAt(0).toLowerCase() + str.slice(1);
@@ -642,9 +455,6 @@ const firstLower = (str) => {
642
455
  * 反转字符串
643
456
  * @param str - 字符串
644
457
  * @returns 反转后的字符串
645
- * @example
646
- * reverse("hello")
647
- * // => "olleh"
648
458
  */
649
459
  const reverse = (str) => {
650
460
  return str.split("").reverse().join("");
@@ -655,9 +465,6 @@ const reverse = (str) => {
655
465
  * 获取 localStorage
656
466
  * @param key - 存储键名
657
467
  * @returns 解析后的值,解析失败则返回原始字符串,键不存在返回 null
658
- * @example
659
- * localGet("user")
660
- * // => { name: "张三" }
661
468
  */
662
469
  const localGet = (key) => {
663
470
  const value = localStorage.getItem(key);
@@ -672,8 +479,6 @@ const localGet = (key) => {
672
479
  * 设置 localStorage
673
480
  * @param key - 存储键名
674
481
  * @param value - 存储值(会自动 JSON 序列化)
675
- * @example
676
- * localSet("user", { name: "张三" })
677
482
  */
678
483
  const localSet = (key, value) => {
679
484
  localStorage.setItem(key, JSON.stringify(value));
@@ -681,16 +486,12 @@ const localSet = (key, value) => {
681
486
  /**
682
487
  * 移除指定 localStorage
683
488
  * @param key - 存储键名
684
- * @example
685
- * localRm("user")
686
489
  */
687
490
  const localRm = (key) => {
688
491
  localStorage.removeItem(key);
689
492
  };
690
493
  /**
691
494
  * 清除所有 localStorage
692
- * @example
693
- * localClear()
694
495
  */
695
496
  const localClear = () => {
696
497
  localStorage.clear();
@@ -703,11 +504,6 @@ const localClear = () => {
703
504
  * @param obj - 要拷贝的值
704
505
  * @param hash - 内部 WeakMap 用于处理循环引用,调用方无需传入
705
506
  * @returns 深拷贝后的值
706
- * @example
707
- * const obj = { a: 1, b: { c: 2 }, d: new Date() };
708
- * const cloned = deepClone(obj);
709
- * // cloned.b !== obj.b
710
- * // cloned.d !== obj.d
711
507
  */
712
508
  function deepClone(obj, hash = /* @__PURE__ */ new WeakMap()) {
713
509
  if (obj === null || typeof obj !== "object") return obj;
@@ -751,9 +547,6 @@ function deepClone(obj, hash = /* @__PURE__ */ new WeakMap()) {
751
547
  * (不支持函数、undefined、Date、RegExp、Map、Set 等)
752
548
  * @param obj - 要拷贝的 JSON 安全值
753
549
  * @returns 深拷贝后的值
754
- * @example
755
- * deepCloneWithJSON({ a: 1, b: [2, 3] })
756
- * // => { a: 1, b: [2, 3] }
757
550
  */
758
551
  function deepCloneWithJSON(obj) {
759
552
  return JSON.parse(JSON.stringify(obj));
@@ -763,10 +556,6 @@ function deepCloneWithJSON(obj) {
763
556
  * 仅拷贝第一层属性,嵌套对象仍共享引用
764
557
  * @param obj - 要拷贝的对象或数组
765
558
  * @returns 浅拷贝后的值
766
- * @example
767
- * const obj = { a: 1, b: { c: 2 } };
768
- * const cloned = shallowClone(obj);
769
- * // cloned.b === obj.b(共享引用)
770
559
  */
771
560
  function shallowClone(obj) {
772
561
  if (obj === null || typeof obj !== "object") return obj;
@@ -779,9 +568,6 @@ function shallowClone(obj) {
779
568
  * Set 去重
780
569
  * @param arr - 数组
781
570
  * @returns 去重后的数组
782
- * @example
783
- * unique([1, 2, 2, 3])
784
- * // => [1, 2, 3]
785
571
  */
786
572
  const unique = (arr) => {
787
573
  return [...new Set(arr)];
@@ -791,9 +577,6 @@ const unique = (arr) => {
791
577
  * @param arr - 对象数组
792
578
  * @param key - 用于去重判定的键名
793
579
  * @returns 去重后的数组
794
- * @example
795
- * uniqueByKey([{ id: 1, name: "a" }, { id: 1, name: "b" }], "id")
796
- * // => [{ id: 1, name: "a" }]
797
580
  */
798
581
  const uniqueByKey = (arr, key) => {
799
582
  return [...new Map(arr.map((item) => [item[key], item])).values()];
@@ -802,9 +585,6 @@ const uniqueByKey = (arr, key) => {
802
585
  * 数值升序
803
586
  * @param arr - 数值数组
804
587
  * @returns 升序排序后的新数组
805
- * @example
806
- * sortNumAsc([3, 1, 2])
807
- * // => [1, 2, 3]
808
588
  */
809
589
  const sortNumAsc = (arr) => {
810
590
  return [...arr].sort((a, b) => a - b);
@@ -813,9 +593,6 @@ const sortNumAsc = (arr) => {
813
593
  * 数值降序
814
594
  * @param arr - 数值数组
815
595
  * @returns 降序排序后的新数组
816
- * @example
817
- * sortNumDesc([1, 3, 2])
818
- * // => [3, 2, 1]
819
596
  */
820
597
  const sortNumDesc = (arr) => {
821
598
  return [...arr].sort((a, b) => b - a);
@@ -826,9 +603,6 @@ const sortNumDesc = (arr) => {
826
603
  * @param key - 用于排序的属性名
827
604
  * @param order - 排序方向,"asc" 升序 / "desc" 降序,默认 "asc"
828
605
  * @returns 排序后的新数组
829
- * @example
830
- * sortByKey([{ age: 30 }, { age: 20 }], "age", "asc")
831
- * // => [{ age: 20 }, { age: 30 }]
832
606
  */
833
607
  const sortByKey = (arr, key, order = "asc") => {
834
608
  return [...arr].sort((a, b) => order === "asc" ? a[key] - b[key] : b[key] - a[key]);
@@ -837,9 +611,6 @@ const sortByKey = (arr, key, order = "asc") => {
837
611
  * 类数组转数组
838
612
  * @param arrayLike - 类数组对象(如 NodeList、arguments)
839
613
  * @returns 转换后的数组
840
- * @example
841
- * toArray(document.querySelectorAll("div"))
842
- * // => [div, div, ...]
843
614
  */
844
615
  const toArray = (arrayLike) => {
845
616
  return Array.from(arrayLike);
@@ -848,9 +619,6 @@ const toArray = (arrayLike) => {
848
619
  * 合并多个数组
849
620
  * @param arrays - 一个或多个数组
850
621
  * @returns 合并后的新数组
851
- * @example
852
- * mergeArrays([1, 2], [3, 4], [5])
853
- * // => [1, 2, 3, 4, 5]
854
622
  */
855
623
  const mergeArrays = (...arrays) => {
856
624
  return [].concat(...arrays);
@@ -860,12 +628,6 @@ const mergeArrays = (...arrays) => {
860
628
  * @param arr - 多维数组
861
629
  * @param depth - 扁平化深度,默认 1(仅展开一层)。传 Infinity 可完全扁平化为一维
862
630
  * @returns 扁平化后的数组
863
- * @example
864
- * flatten([1, [2, [3, 4]], 5])
865
- * // => [1, 2, [3, 4], 5]
866
- * @example
867
- * flatten([1, [2, [3, 4]], 5], Infinity)
868
- * // => [1, 2, 3, 4, 5]
869
631
  */
870
632
  const flatten = (arr, depth = 1) => {
871
633
  return arr.flat(depth);
@@ -876,9 +638,6 @@ const flatten = (arr, depth = 1) => {
876
638
  * @param key - 要匹配的键名
877
639
  * @param value - 要匹配的键值
878
640
  * @returns 第一个匹配的对象,无匹配则返回 undefined
879
- * @example
880
- * arrFind([{ id: 1, name: "a" }, { id: 2, name: "b" }], "id", 2)
881
- * // => { id: 2, name: "b" }
882
641
  */
883
642
  const arrFind = (arr, key, value) => {
884
643
  return arr.find((item) => item[key] === value);
@@ -888,9 +647,6 @@ const arrFind = (arr, key, value) => {
888
647
  * @param arr - 对象数组
889
648
  * @param key - 用于分组的属性名
890
649
  * @returns 以属性值为键、对应数组为值的对象
891
- * @example
892
- * groupBy([{ type: "fruit", name: "apple" }, { type: "vegetable", name: "carrot" }], "type")
893
- * // => { fruit: [{ type: "fruit", name: "apple" }], vegetable: [{ type: "vegetable", name: "carrot" }] }
894
650
  */
895
651
  const groupBy = (arr, key) => {
896
652
  return arr.reduce((acc, item) => {
@@ -904,9 +660,6 @@ const groupBy = (arr, key) => {
904
660
  * 移除对象中值为空(null / undefined / 空字符串)的属性
905
661
  * @param obj - 待过滤的对象
906
662
  * @returns 过滤后的新对象
907
- * @example
908
- * filterEmptyValues({ a: 1, b: "", c: null, d: 3 })
909
- * // => { a: 1, d: 3 }
910
663
  */
911
664
  const filterEmptyValues = (obj) => {
912
665
  return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== null && v !== void 0 && v !== ""));
@@ -916,9 +669,6 @@ const filterEmptyValues = (obj) => {
916
669
  * @param length - 数组长度
917
670
  * @param mapFn - 映射函数,接收索引返回元素值,默认为返回索引
918
671
  * @returns 生成的数组
919
- * @example
920
- * createRange(5)
921
- * // => [0, 1, 2, 3, 4]
922
672
  */
923
673
  const createRange = (length, mapFn) => {
924
674
  return Array.from({ length }, (_, i) => mapFn ? mapFn(i) : i);
@@ -930,8 +680,6 @@ const createRange = (length, mapFn) => {
930
680
  * @param name - Cookie 名称
931
681
  * @param value - Cookie 值
932
682
  * @param days - 有效天数,默认 7 天
933
- * @example
934
- * setCookie("token", "abc123", 30)
935
683
  */
936
684
  const setCookie = (name, value, days = 0) => {
937
685
  const expires = /* @__PURE__ */ new Date();
@@ -942,9 +690,6 @@ const setCookie = (name, value, days = 0) => {
942
690
  * 获取 Cookie
943
691
  * @param name - Cookie 名称
944
692
  * @returns Cookie 值,不存在则返回 null
945
- * @example
946
- * getCookie("token")
947
- * // => "abc123"
948
693
  */
949
694
  const getCookie = (name) => {
950
695
  const match = document.cookie.match(new RegExp("(^| )" + encodeURIComponent(name) + "=([^;]+)"));
@@ -953,8 +698,6 @@ const getCookie = (name) => {
953
698
  /**
954
699
  * 删除 Cookie
955
700
  * @param name - Cookie 名称
956
- * @example
957
- * delCookie("token")
958
701
  */
959
702
  const delCookie = (name) => {
960
703
  setCookie(name, "", -1);
@@ -965,9 +708,6 @@ const delCookie = (name) => {
965
708
  * 获取 URL 参数对象
966
709
  * @param url - URL 字符串,默认使用当前页面地址
967
710
  * @returns 参数键值对对象
968
- * @example
969
- * getUrlParams("https://example.com?a=1&b=2")
970
- * // => { a: "1", b: "2" }
971
711
  */
972
712
  const getUrlParams = (url) => {
973
713
  const params = {};
@@ -981,9 +721,6 @@ const getUrlParams = (url) => {
981
721
  * @param key - 参数名
982
722
  * @param url - URL 字符串,默认使用当前页面地址
983
723
  * @returns 参数值,不存在则返回 null
984
- * @example
985
- * getUrlParam("a", "https://example.com?a=1")
986
- * // => "1"
987
724
  */
988
725
  const getUrlParam = (key, url) => {
989
726
  return new URL(url || window.location.href).searchParams.get(key);
@@ -992,9 +729,6 @@ const getUrlParam = (key, url) => {
992
729
  * 对象转 URL 参数字符串
993
730
  * @param params - 参数键值对对象,值为 null/undefined 的项会被过滤
994
731
  * @returns URL 参数字符串(不含 ? 前缀)
995
- * @example
996
- * toQueryString({ a: 1, b: "hello", c: null })
997
- * // => "a=1&b=hello"
998
732
  */
999
733
  const toQueryString = (params) => {
1000
734
  return Object.entries(params).filter(([, v]) => v !== void 0 && v !== null).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
@@ -1004,9 +738,6 @@ const toQueryString = (params) => {
1004
738
  * 优先使用 Clipboard API,失败时降级为 execCommand
1005
739
  * @param text - 要复制的文本
1006
740
  * @returns 复制成功返回 true,失败返回 false
1007
- * @example
1008
- * await copyToClipboard("Hello World")
1009
- * // => true
1010
741
  */
1011
742
  const copyToClipboard = async (text) => {
1012
743
  if (navigator.clipboard) try {
@@ -1030,8 +761,6 @@ const copyToClipboard = async (text) => {
1030
761
  * @param content - 文件内容
1031
762
  * @param filename - 文件名
1032
763
  * @param mimeType - MIME 类型,默认 "text/plain"
1033
- * @example
1034
- * downloadFile("Hello", "hello.txt")
1035
764
  */
1036
765
  const downloadFile = (content, filename, mimeType = "text/plain") => {
1037
766
  const blob = new Blob([content], { type: mimeType });
@@ -1046,8 +775,6 @@ const downloadFile = (content, filename, mimeType = "text/plain") => {
1046
775
  * 导出 JSON 为文件
1047
776
  * @param data - 要导出的数据
1048
777
  * @param filename - 文件名,默认 "data.json"
1049
- * @example
1050
- * exportJSON({ name: "张三", age: 30 })
1051
778
  */
1052
779
  const exportJSON = (data, filename = "data.json") => {
1053
780
  downloadFile(JSON.stringify(data, null, 2), filename, "application/json");
@@ -1055,8 +782,6 @@ const exportJSON = (data, filename = "data.json") => {
1055
782
  /**
1056
783
  * 滚动到顶部
1057
784
  * @param behavior - 滚动行为,"smooth" 平滑 / "auto" 瞬间,默认 "smooth"
1058
- * @example
1059
- * scrollToTop()
1060
785
  */
1061
786
  const scrollToTop = (behavior = "smooth") => {
1062
787
  window.scrollTo({
@@ -1067,8 +792,6 @@ const scrollToTop = (behavior = "smooth") => {
1067
792
  /**
1068
793
  * 滚动到底部
1069
794
  * @param behavior - 滚动行为,"smooth" 平滑 / "auto" 瞬间,默认 "smooth"
1070
- * @example
1071
- * scrollToBottom()
1072
795
  */
1073
796
  const scrollToBottom = (behavior = "smooth") => {
1074
797
  window.scrollTo({
@@ -1080,9 +803,6 @@ const scrollToBottom = (behavior = "smooth") => {
1080
803
  * 监听页面滚动(requestAnimationFrame 节流)
1081
804
  * @param callback - 滚动回调,接收当前 scrollY 值
1082
805
  * @returns 清理函数,调用后移除事件监听
1083
- * @example
1084
- * const cleanup = onScroll((y) => console.log(y));
1085
- * cleanup(); // 停止监听
1086
806
  */
1087
807
  const onScroll = (callback) => {
1088
808
  let ticking = false;
@@ -1105,12 +825,6 @@ const onScroll = (callback) => {
1105
825
  * @param onLeave - 元素离开可视区域时的回调(可选)
1106
826
  * @param options - IntersectionObserver 配置项
1107
827
  * @returns 清理函数,调用后停止观察
1108
- * @example
1109
- * const cleanup = observeIntersection(
1110
- * document.querySelector(".footer")!,
1111
- * () => loadMore(10),
1112
- * );
1113
- * cleanup(); // 停止观察
1114
828
  */
1115
829
  const observeIntersection = (target, onEnter, onLeave, options) => {
1116
830
  const observer = new IntersectionObserver((entries) => {
@@ -1131,10 +845,6 @@ const observeIntersection = (target, onEnter, onLeave, options) => {
1131
845
  * @param options.leading - 首次调用是否立即执行,默认 false
1132
846
  * @param options.trailing - 停止调用后是否延迟执行,默认 true
1133
847
  * @returns 防抖后的函数,附带 cancel 方法
1134
- * @example
1135
- * const fn = debounce((val: string) => console.log(val), 500)
1136
- * fn("a"); fn("b"); fn("c")
1137
- * // => "c"
1138
848
  */
1139
849
  const debounce = (fn, delay = 300, { leading = false, trailing = true } = {}) => {
1140
850
  let timer = null;
@@ -1171,10 +881,6 @@ const debounce = (fn, delay = 300, { leading = false, trailing = true } = {}) =>
1171
881
  * @param options.leading - 首次调用是否立即执行,默认 true
1172
882
  * @param options.trailing - 最后一次调用后是否尾部执行,默认 true
1173
883
  * @returns 节流后的函数,附带 cancel 方法
1174
- * @example
1175
- * const fn = throttle((val: string) => console.log(val), 500)
1176
- * fn("a"); fn("b"); fn("c")
1177
- * // => "a",500ms 后输出 "c"
1178
884
  */
1179
885
  const throttle = (fn, interval = 300, { leading = true, trailing = true } = {}) => {
1180
886
  let timer = null;