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