pen-it 1.0.8 → 1.0.10

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/README.md CHANGED
@@ -11,594 +11,734 @@ pnpm add pen-it
11
11
  ## 使用
12
12
 
13
13
  ```ts
14
- import { isArray, formatFull, deepClone, unique } from 'pen-it'
14
+ import { isArray, formatFull, deepClone, unique } from "pen-it";
15
15
  ```
16
16
 
17
+ ## API
18
+
19
+ ### 类型判断
20
+
17
21
  ---
18
22
 
19
- ## API
23
+ #### isArray(value)
24
+
25
+ > — 判断是否为数组。
26
+
27
+ ```ts
28
+ isArray([1, 2, 3]); // true
29
+ ```
30
+
31
+ #### isObject(value)
32
+
33
+ > — 判断是否为对象(不含数组)。
34
+
35
+ ```ts
36
+ isObject({ a: 1 }); // true
37
+ ```
38
+
39
+ #### is(val, type)
40
+
41
+ > — 通用类型判断(内部工具)。
42
+
43
+ ```ts
44
+ is([], "Array"); // true
45
+ ```
46
+
47
+ #### isFunction(val)
48
+
49
+ > — 判断是否为函数。
50
+
51
+ ```ts
52
+ isFunction(() => {}); // true
53
+ ```
54
+
55
+ #### isAsyncFunction(val)
56
+
57
+ > — 判断是否为异步函数。
58
+
59
+ ```ts
60
+ isAsyncFunction(async () => {}); // true
61
+ ```
62
+
63
+ #### isPromise(value)
64
+
65
+ > — 判断是否为 Promise。
66
+
67
+ ```ts
68
+ isPromise(Promise.resolve()); // true
69
+ ```
20
70
 
21
- ### 类型判断 — `is`
71
+ #### isDate(val)
22
72
 
23
- - **`isArray(value)`** 判断是否为数组。
73
+ >判断是否为 Date 对象。
24
74
 
25
- ```ts
26
- isArray([1, 2, 3]) // true
27
- ```
75
+ ```ts
76
+ isDate(new Date()); // true
77
+ ```
28
78
 
29
- - **`isObject(value)`** — 判断是否为对象(不含数组)。
79
+ #### isNumber(val)
30
80
 
31
- ```ts
32
- isObject({ a: 1 }) // true
33
- ```
81
+ > — 判断是否为数字(含 NaN/Infinity)。
34
82
 
35
- - **`is(val, type)`** — 通用类型判断(内部工具)。
83
+ ```ts
84
+ isNumber(42); // true
85
+ ```
36
86
 
37
- ```ts
38
- is([], 'Array') // true
39
- ```
87
+ #### isInt(val)
40
88
 
41
- - **`isFunction(val)`** 判断是否为函数。
89
+ >判断是否为整数。
42
90
 
43
- ```ts
44
- isFunction(() => {}) // true
45
- ```
91
+ ```ts
92
+ isInt(42); // true
93
+ ```
46
94
 
47
- - **`isAsyncFunction(val)`** — 判断是否为异步函数。
95
+ #### isFloat(val)
48
96
 
49
- ```ts
50
- isAsyncFunction(async () => {}) // true
51
- ```
97
+ > — 判断是否为浮点数。
52
98
 
53
- - **`isPromise(value)`** — 判断是否为 Promise。
99
+ ```ts
100
+ isFloat(3.14); // true
101
+ ```
54
102
 
55
- ```ts
56
- isPromise(Promise.resolve()) // true
57
- ```
103
+ #### isString(val)
58
104
 
59
- - **`isDate(val)`** 判断是否为 Date 对象。
105
+ >判断是否为字符串。
60
106
 
61
- ```ts
62
- isDate(new Date()) // true
63
- ```
107
+ ```ts
108
+ isString("hello"); // true
109
+ ```
64
110
 
65
- - **`isNumber(val)`** — 判断是否为数字(含 NaN/Infinity)。
111
+ #### isBoolean(val)
66
112
 
67
- ```ts
68
- isNumber(42) // true
69
- ```
113
+ > — 判断是否为布尔值。
70
114
 
71
- - **`isInt(val)`** — 判断是否为整数。
115
+ ```ts
116
+ isBoolean(true); // true
117
+ ```
72
118
 
73
- ```ts
74
- isInt(42) // true
75
- ```
119
+ #### isSymbol(value)
76
120
 
77
- - **`isFloat(val)`** 判断是否为浮点数。
121
+ >判断是否为 Symbol。
78
122
 
79
- ```ts
80
- isFloat(3.14) // true
81
- ```
123
+ ```ts
124
+ isSymbol(Symbol("foo")); // true
125
+ ```
126
+
127
+ #### isPrimitive(value)
128
+
129
+ > — 判断是否为原始类型。
130
+
131
+ ```ts
132
+ isPrimitive(42); // true
133
+ ```
134
+
135
+ #### isNull(val)
136
+
137
+ > — 判断是否为 null。
138
+
139
+ ```ts
140
+ isNull(null); // true
141
+ ```
142
+
143
+ #### isDef(val)
144
+
145
+ > — 判断是否不是 undefined。
146
+
147
+ ```ts
148
+ isDef("hello"); // true
149
+ ```
82
150
 
83
- - **`isString(val)`** — 判断是否为字符串。
151
+ #### isUnDef(val)
84
152
 
85
- ```ts
86
- isString('hello') // true
87
- ```
153
+ > — 判断是否为 undefined。
88
154
 
89
- - **`isBoolean(val)`** — 判断是否为布尔值。
155
+ ```ts
156
+ isUnDef(undefined); // true
157
+ ```
90
158
 
91
- ```ts
92
- isBoolean(true) // true
93
- ```
159
+ #### isNullOrUnDef(val)
94
160
 
95
- - **`isSymbol(value)`** — 判断是否为 Symbol
161
+ > — 判断是否为 null 或 undefined
96
162
 
97
- ```ts
98
- isSymbol(Symbol('foo')) // true
99
- ```
163
+ ```ts
164
+ isNullOrUnDef(null); // true
165
+ ```
100
166
 
101
- - **`isPrimitive(value)`** — 判断是否为原始类型。
167
+ #### isEmpty(value)
102
168
 
103
- ```ts
104
- isPrimitive(42) // true
105
- ```
169
+ > — 判断是否为空(完备版:支持 Date/Map/Set 等)。
106
170
 
107
- - **`isNull(val)`** — 判断是否为 null。
171
+ ```ts
172
+ isEmpty(""); // true
173
+ isEmpty([]); // true
174
+ isEmpty({}); // true
175
+ ```
108
176
 
109
- ```ts
110
- isNull(null) // true
111
- ```
177
+ #### isEmptySv(value)
112
178
 
113
- - **`isDef(val)`** 判断是否不是 undefined。
179
+ >判断是否为空(简化版)。
114
180
 
115
- ```ts
116
- isDef('hello') // true
117
- ```
181
+ ```ts
182
+ isEmptySv([]); // true
183
+ ```
118
184
 
119
- - **`isUnDef(val)`** — 判断是否为 undefined。
185
+ #### isEqual(x, y)
120
186
 
121
- ```ts
122
- isUnDef(undefined) // true
123
- ```
187
+ > — 深度相等比较(支持 Date/RegExp)。
124
188
 
125
- - **`isNullOrUnDef(val)`** — 判断是否为 null 或 undefined。
189
+ ```ts
190
+ isEqual({ a: 1 }, { a: 1 }); // true
191
+ ```
126
192
 
127
- ```ts
128
- isNullOrUnDef(null) // true
129
- ```
193
+ #### isHexColor(str)
130
194
 
131
- - **`isEmpty(value)`** 判断是否为空(完备版:支持 Date/Map/Set 等)。
195
+ >判断是否为十六进制颜色。
132
196
 
133
- ```ts
134
- isEmpty('') // true
135
- isEmpty([]) // true
136
- isEmpty({}) // true
137
- ```
197
+ ```ts
198
+ isHexColor("#fff"); // true
199
+ ```
138
200
 
139
- - **`isEmptySv(value)`** — 判断是否为空(简化版)。
201
+ #### isValidEmail(email)
140
202
 
141
- ```ts
142
- isEmptySv([]) // true
143
- ```
203
+ > — 判断是否为有效邮箱。
144
204
 
145
- - **`isEqual(x, y)`** — 深度相等比较(支持 Date/RegExp)。
205
+ ```ts
206
+ isValidEmail("a@b.com"); // true
207
+ ```
146
208
 
147
- ```ts
148
- isEqual({ a: 1 }, { a: 1 }) // true
149
- ```
209
+ #### isPC()
150
210
 
151
- - **`isHexColor(str)`** 判断是否为十六进制颜色。
211
+ >判断是否为浏览器环境。
152
212
 
153
- ```ts
154
- isHexColor('#fff') // true
155
- ```
213
+ ```ts
214
+ isPC(); // true
215
+ ```
156
216
 
157
- - **`isValidEmail(email)`** — 判断是否为有效邮箱。
217
+ #### isWindow(val)
158
218
 
159
- ```ts
160
- isValidEmail('a@b.com') // true
161
- ```
219
+ > — 判断是否为 window 对象。
162
220
 
163
- - **`isPC()`** — 判断是否为浏览器环境。
221
+ ```ts
222
+ isWindow(window); // true
223
+ ```
164
224
 
165
- ```ts
166
- isPC() // true
167
- ```
225
+ #### isElement(val)
168
226
 
169
- - **`isWindow(val)`** — 判断是否为 window 对象。
227
+ > — 判断是否为 DOM 元素。
170
228
 
171
- ```ts
172
- isWindow(window) // true
173
- ```
229
+ ```ts
230
+ isElement(document.body); // true
231
+ ```
174
232
 
175
- - **`isElement(val)`** — 判断是否为 DOM 元素。
233
+ #### isIOS()
176
234
 
177
- ```ts
178
- isElement(document.body) // true
179
- ```
235
+ > — 判断设备是否为 iOS。
180
236
 
181
- - **`isIOS()`** — 判断设备是否为 iOS。
237
+ ```ts
238
+ isIOS(); // true
239
+ ```
182
240
 
183
- ```ts
184
- isIOS() // true
185
- ```
241
+ ### 时间日期格式化
186
242
 
187
243
  ---
188
244
 
189
- ### 日期时间格式化 — `format`
245
+ #### formatFull(date)
190
246
 
191
- - **`formatFull(date)`** — 完整日期时间(斜杠分隔)。
247
+ > — 完整日期时间(斜杠分隔)。
192
248
 
193
- ```ts
194
- formatFull(new Date()) // "2026/06/03 14:30:45"
195
- ```
249
+ ```ts
250
+ formatFull(new Date()); // "2026/06/03 14:30:45"
251
+ ```
196
252
 
197
- - **`formatFullReplace(date)`** — 完整日期时间(短横线分隔)。
253
+ #### formatFullReplace(date)
198
254
 
199
- ```ts
200
- formatFullReplace(new Date()) // "2026-06-03 14:30:45"
201
- ```
255
+ > — 完整日期时间(短横线分隔)。
256
+
257
+ ```ts
258
+ formatFullReplace(new Date()); // "2026-06-03 14:30:45"
259
+ ```
260
+
261
+ #### formatYMD(date)
262
+
263
+ > — 中文年月日。
264
+
265
+ ```ts
266
+ formatYMD(new Date()); // "2026年6月3日"
267
+ ```
202
268
 
203
- - **`formatYMD(date)`** — 中文年月日。
269
+ #### formatWeek(date)
204
270
 
205
- ```ts
206
- formatYMD(new Date()) // "2026年6月3日"
207
- ```
271
+ > — 星期几。
208
272
 
209
- - **`formatWeek(date)`** — 星期几。
273
+ ```ts
274
+ formatWeek(new Date()); // "星期三"
275
+ ```
210
276
 
211
- ```ts
212
- formatWeek(new Date()) // "星期三"
213
- ```
277
+ ### 数字与货币格式化
214
278
 
215
279
  ---
216
280
 
217
- ### 数字与货币格式化 — `format`
281
+ #### formatRmb(value, options)
282
+
283
+ > — 货币格式化(人民币)。
284
+
285
+ ```ts
286
+ formatRmb(1234.56, { type: "zh-CN", currency: "CNY" }); // "¥1,234.56"
287
+ ```
288
+
289
+ #### formatNum(value)
218
290
 
219
- - **`formatRmb(value, options)`** 货币格式化(人民币)。
291
+ >千位分隔符。
220
292
 
221
- ```ts
222
- formatRmb(1234.56, { type: 'zh-CN', currency: 'CNY' }) // "¥1,234.56"
223
- ```
293
+ ```ts
294
+ formatNum(1234567); // "1,234,567"
295
+ ```
224
296
 
225
- - **`formatNum(value)`** — 千位分隔符。
297
+ #### percentCN(value, digit)
226
298
 
227
- ```ts
228
- formatNum(1234567) // "1,234,567"
229
- ```
299
+ > — 百分比格式化。
230
300
 
231
- - **`percentCN(value, digit)`** — 百分比格式化。
301
+ ```ts
302
+ percentCN(0.1234, 2); // "12.34%"
303
+ ```
232
304
 
233
- ```ts
234
- percentCN(0.1234, 2) // "12.34%"
235
- ```
305
+ #### compactEN(value)
236
306
 
237
- - **`compactEN(value)`** — 大数简化(英文缩写)。
307
+ > — 大数简化(英文缩写)。
238
308
 
239
- ```ts
240
- compactEN(12345) // "12K"
241
- ```
309
+ ```ts
310
+ compactEN(12345); // "12K"
311
+ ```
242
312
 
243
- - **`compactCN(value)`** — 大数简化(中文缩写)。
313
+ #### compactCN(value)
244
314
 
245
- ```ts
246
- compactCN(12345) // "1.2万"
247
- ```
315
+ > — 大数简化(中文缩写)。
248
316
 
249
- - **`signed(value, digit)`** — 带正负号显示。
317
+ ```ts
318
+ compactCN(12345); // "1.2万"
319
+ ```
250
320
 
251
- ```ts
252
- signed(42, 1) // "+42.0"
253
- ```
321
+ #### signed(value, digit)
322
+
323
+ > — 带正负号显示。
324
+
325
+ ```ts
326
+ signed(42, 1); // "+42.0"
327
+ ```
328
+
329
+ ### 字符串处理
254
330
 
255
331
  ---
256
332
 
257
- ### 字符串处理 — `format`
333
+ #### maskPhone(phone)
258
334
 
259
- - **`maskPhone(phone)`** — 手机号脱敏(隐藏中间4位)。
335
+ > — 手机号脱敏(隐藏中间4位)。
260
336
 
261
- ```ts
262
- maskPhone('13812345678') // "138****5678"
263
- ```
337
+ ```ts
338
+ maskPhone("13812345678"); // "138****5678"
339
+ ```
264
340
 
265
- - **`spacePhone(phone)`** — 手机号空格分隔。
341
+ #### spacePhone(phone)
266
342
 
267
- ```ts
268
- spacePhone('13812345678') // "138 1234 5678"
269
- ```
343
+ > — 手机号空格分隔。
270
344
 
271
- - **`capitalize(str)`** — 每个单词首字母大写。
345
+ ```ts
346
+ spacePhone("13812345678"); // "138 1234 5678"
347
+ ```
272
348
 
273
- ```ts
274
- capitalize('hello world') // "Hello World"
275
- ```
349
+ #### capitalize(str)
276
350
 
277
- - **`kebabToCamel(str)`** 短横线转小驼峰。
351
+ >每个单词首字母大写。
278
352
 
279
- ```ts
280
- kebabToCamel('hello-world') // "helloWorld"
281
- ```
353
+ ```ts
354
+ capitalize("hello world"); // "Hello World"
355
+ ```
282
356
 
283
- - **`camelToKebab(str)`** — 驼峰转短横线。
357
+ #### kebabToCamel(str)
284
358
 
285
- ```ts
286
- camelToKebab('helloWorld') // "hello-world"
287
- ```
359
+ > — 短横线转小驼峰。
288
360
 
289
- - **`toCamel(str)`** — 下划线转驼峰。
361
+ ```ts
362
+ kebabToCamel("hello-world"); // "helloWorld"
363
+ ```
290
364
 
291
- ```ts
292
- toCamel('hello_world') // "helloWorld"
293
- ```
365
+ #### camelToKebab(str)
294
366
 
295
- - **`firstUpper(str)`** 首字母大写。
367
+ >驼峰转短横线。
296
368
 
297
- ```ts
298
- firstUpper('hello') // "Hello"
299
- ```
369
+ ```ts
370
+ camelToKebab("helloWorld"); // "hello-world"
371
+ ```
300
372
 
301
- - **`firstLower(str)`** — 首字母小写。
373
+ #### toCamel(str)
302
374
 
303
- ```ts
304
- firstLower('Hello') // "hello"
305
- ```
375
+ > — 下划线转驼峰。
306
376
 
307
- - **`reverse(str)`** — 反转字符串。
377
+ ```ts
378
+ toCamel("hello_world"); // "helloWorld"
379
+ ```
380
+
381
+ #### firstUpper(str)
382
+
383
+ > — 首字母大写。
384
+
385
+ ```ts
386
+ firstUpper("hello"); // "Hello"
387
+ ```
388
+
389
+ #### firstLower(str)
308
390
 
309
- ```ts
310
- reverse('hello') // "olleh"
311
- ```
391
+ > — 首字母小写。
312
392
 
313
- - **`trimAll(str)`** — 去除所有空格。
393
+ ```ts
394
+ firstLower("Hello"); // "hello"
395
+ ```
396
+
397
+ #### reverse(str)
398
+
399
+ > — 反转字符串。
314
400
 
315
- ```ts
316
- trimAll(' h e l lo ') // "hello"
317
- ```
401
+ ```ts
402
+ reverse("hello"); // "olleh"
403
+ ```
318
404
 
319
- - **`truncate(str, max, suffix?)`** — 超长文本截断。
405
+ #### trimAll(str)
320
406
 
321
- ```ts
322
- truncate('Hello World', 8) // "Hello..."
323
- ```
407
+ > — 去除所有空格。
324
408
 
325
- - **`truncateByWords(str, max, suffix?)`** — 按字数截断(中文友好)。
409
+ ```ts
410
+ trimAll(" h e l lo "); // "hello"
411
+ ```
326
412
 
327
- ```ts
328
- truncateByWords('你好世界欢迎你', 4) // "你好世界..."
329
- ```
413
+ #### truncate(str, max, suffix?)
414
+
415
+ > — 超长文本截断。
416
+
417
+ ```ts
418
+ truncate("Hello World", 8); // "Hello..."
419
+ ```
420
+
421
+ #### truncateByWords(str, max, suffix?)
422
+
423
+ > — 按字数截断(中文友好)。
424
+
425
+ ```ts
426
+ truncateByWords("你好世界欢迎你", 4); // "你好世界..."
427
+ ```
428
+
429
+ ### 存储
330
430
 
331
431
  ---
332
432
 
333
- ### 存储 — `storage`
433
+ #### localGet<T>(key)
434
+
435
+ > — 获取 localStorage(自动 JSON 解析)。
436
+
437
+ ```ts
438
+ localGet("user"); // { name: '张三' }
439
+ ```
440
+
441
+ #### localSet(key, value)
334
442
 
335
- - **`localGet<T>(key)`**获取 localStorage(自动 JSON 解析)。
443
+ > — 设置 localStorage(自动 JSON 序列化)。
336
444
 
337
- ```ts
338
- localGet('user') // { name: '张三' }
339
- ```
445
+ ```ts
446
+ localSet("user", { name: "张三" });
447
+ ```
340
448
 
341
- - **`localSet(key, value)`** — 设置 localStorage(自动 JSON 序列化)。
449
+ #### localRm(key)
342
450
 
343
- ```ts
344
- localSet('user', { name: '张三' })
345
- ```
451
+ > — 移除指定 localStorage。
452
+
453
+ ```ts
454
+ localRm("user");
455
+ ```
346
456
 
347
- - **`localRm(key)`** — 移除指定 localStorage。
457
+ #### localClear()
348
458
 
349
- ```ts
350
- localRm('user')
351
- ```
459
+ > — 清除所有 localStorage。
352
460
 
353
- - **`localClear()`** — 清除所有 localStorage。
461
+ ```ts
462
+ localClear();
463
+ ```
354
464
 
355
- ```ts
356
- localClear()
357
- ```
465
+ ### 拷贝
358
466
 
359
467
  ---
360
468
 
361
- ### 拷贝 — `copy`
469
+ #### deepClone(obj)
470
+
471
+ > — 递归深拷贝(支持 Date/RegExp/Map/Set/循环引用)。
362
472
 
363
- - **`deepClone(obj)`** — 递归深拷贝(支持 Date/RegExp/Map/Set/循环引用)。
473
+ ```ts
474
+ deepClone({ a: 1, b: { c: 2 } });
475
+ ```
476
+
477
+ #### deepCloneWithJSON(obj)
478
+
479
+ > — JSON 深拷贝(仅 JSON 安全类型)。
364
480
 
365
- ```ts
366
- deepClone({ a: 1, b: { c: 2 } })
367
- ```
481
+ ```ts
482
+ deepCloneWithJSON({ a: 1 });
483
+ ```
368
484
 
369
- - **`deepCloneWithJSON(obj)`** — JSON 深拷贝(仅 JSON 安全类型)。
485
+ #### structClone(obj, options?)
370
486
 
371
- ```ts
372
- deepCloneWithJSON({ a: 1 })
373
- ```
487
+ > — structuredClone 深拷贝(不支持函数/Symbol)。
374
488
 
375
- - **`shallowClone(obj)`** — 浅拷贝(仅第一层)。
489
+ ```ts
490
+ structClone({ a: 1, b: { c: 2 } });
491
+ ```
376
492
 
377
- ```ts
378
- shallowClone({ a: 1, b: { c: 2 } })
379
- ```
493
+ #### shallowClone(obj)
494
+
495
+ > — 浅拷贝(仅第一层)。
496
+
497
+ ```ts
498
+ shallowClone({ a: 1, b: { c: 2 } });
499
+ ```
500
+
501
+ ### 数组
380
502
 
381
503
  ---
382
504
 
383
- ### 数组 — `array`
505
+ #### unique(arr)
384
506
 
385
- - **`unique(arr)`** — Set 去重。
507
+ > — Set 去重。
386
508
 
387
- ```ts
388
- unique([1, 2, 2, 3]) // [1, 2, 3]
389
- ```
509
+ ```ts
510
+ unique([1, 2, 2, 3]); // [1, 2, 3]
511
+ ```
390
512
 
391
- - **`uniqueByKey(arr, key)`** — 对象数组按 key 去重。
513
+ #### uniqueByKey(arr, key)
392
514
 
393
- ```ts
394
- uniqueByKey([{ id: 1 }, { id: 1 }], 'id')
395
- ```
515
+ > — 对象数组按 key 去重。
396
516
 
397
- - **`sortNumAsc(arr)`** — 数值升序。
517
+ ```ts
518
+ uniqueByKey([{ id: 1 }, { id: 1 }], "id");
519
+ ```
398
520
 
399
- ```ts
400
- sortNumAsc([3, 1, 2]) // [1, 2, 3]
401
- ```
521
+ #### sortNumAsc(arr)
402
522
 
403
- - **`sortNumDesc(arr)`** 数值降序。
523
+ >数值升序。
404
524
 
405
- ```ts
406
- sortNumDesc([1, 3, 2]) // [3, 2, 1]
407
- ```
525
+ ```ts
526
+ sortNumAsc([3, 1, 2]); // [1, 2, 3]
527
+ ```
408
528
 
409
- - **`sortByKey(arr, key, order?)`** — 按对象属性排序。
529
+ #### sortNumDesc(arr)
410
530
 
411
- ```ts
412
- sortByKey([{ age: 30 }, { age: 20 }], 'age')
413
- ```
531
+ > — 数值降序。
414
532
 
415
- - **`toArray(arrayLike)`** — 类数组转数组。
533
+ ```ts
534
+ sortNumDesc([1, 3, 2]); // [3, 2, 1]
535
+ ```
416
536
 
417
- ```ts
418
- toArray(document.querySelectorAll('div'))
419
- ```
537
+ #### sortByKey(arr, key, order?)
420
538
 
421
- - **`mergeArrays(...arrays)`** 合并多个数组。
539
+ >按对象属性排序。
422
540
 
423
- ```ts
424
- mergeArrays([1, 2], [3, 4], [5]) // [1, 2, 3, 4, 5]
425
- ```
541
+ ```ts
542
+ sortByKey([{ age: 30 }, { age: 20 }], "age");
543
+ ```
426
544
 
427
- - **`flatten(arr, depth?)`** — 多维数组扁平化到指定层级(默认 1 层,传 `Infinity` 完全展开)。
545
+ #### toArray(arrayLike)
428
546
 
429
- ```ts
430
- flatten([1, [2, [3, 4]], 5]) // [1, 2, [3, 4], 5]
431
- flatten([1, [2, [3, 4]], 5], Infinity) // [1, 2, 3, 4, 5]
432
- ```
547
+ > — 类数组转数组。
433
548
 
434
- - **`arrFind(arr, key, value)`** — 对象数组中按 key-value 查找第一个匹配项。
549
+ ```ts
550
+ toArray(document.querySelectorAll("div"));
551
+ ```
435
552
 
436
- ```ts
437
- arrFind([{ id: 1 }, { id: 2 }], 'id', 2) // { id: 2 }
438
- ```
553
+ #### mergeArrays(...arrays)
439
554
 
440
- - **`groupBy(arr, key)`** 对象数组按指定属性分组。
555
+ >合并多个数组。
556
+
557
+ ```ts
558
+ mergeArrays([1, 2], [3, 4], [5]); // [1, 2, 3, 4, 5]
559
+ ```
441
560
 
442
- ```ts
443
- groupBy([{ type: 'fruit' }, { type: 'vegetable' }], 'type')
444
- // => { fruit: [...], vegetable: [...] }
445
- ```
561
+ #### flatten(arr, depth?)
446
562
 
447
- - **`filterEmptyValues(obj)`** 移除对象中值为空(null / undefined / 空字符串)的属性。
563
+ >多维数组扁平化到指定层级(默认 1 层,传 `Infinity` 完全展开)。
448
564
 
449
- ```ts
450
- filterEmptyValues({ a: 1, b: '', c: null }) // { a: 1 }
451
- ```
565
+ ```ts
566
+ flatten([1, [2, [3, 4]], 5]); // [1, 2, [3, 4], 5]
567
+ flatten([1, [2, [3, 4]], 5], Infinity); // [1, 2, 3, 4, 5]
568
+ ```
452
569
 
453
- - **`createRange(length, mapFn?)`** — 快速生成范围数组。
570
+ #### arrFind(arr, key, value)
454
571
 
455
- ```ts
456
- createRange(5) // [0, 1, 2, 3, 4]
457
- createRange(3, (i) => i * 2) // [0, 2, 4]
458
- ```
572
+ > — 对象数组中按 key-value 查找第一个匹配项。
459
573
 
460
- ---
574
+ ```ts
575
+ arrFind([{ id: 1 }, { id: 2 }], "id", 2); // { id: 2 }
576
+ ```
461
577
 
462
- ### Cookie — `cookie`
578
+ #### groupBy(arr, key)
463
579
 
464
- - **`setCookie(name, value, days?)`** 设置 Cookie(默认7天)。
580
+ >对象数组按指定属性分组。
581
+
582
+ ```ts
583
+ groupBy([{ type: "fruit" }, { type: "vegetable" }], "type");
584
+ // => { fruit: [...], vegetable: [...] }
585
+ ```
465
586
 
466
- ```ts
467
- setCookie('token', 'abc123', 30)
468
- ```
587
+ #### filterEmptyValues(obj)
469
588
 
470
- - **`getCookie(name)`** 获取 Cookie。
589
+ >移除对象中值为空(null / undefined / 空字符串)的属性。
471
590
 
472
- ```ts
473
- getCookie('token') // "abc123"
474
- ```
591
+ ```ts
592
+ filterEmptyValues({ a: 1, b: "", c: null }); // { a: 1 }
593
+ ```
475
594
 
476
- - **`delCookie(name)`** — 删除 Cookie。
595
+ #### createRange(length, mapFn?)
477
596
 
478
- ```ts
479
- delCookie('token')
480
- ```
597
+ > — 快速生成范围数组。
598
+
599
+ ```ts
600
+ createRange(5); // [0, 1, 2, 3, 4]
601
+ createRange(3, (i) => i * 2); // [0, 2, 4]
602
+ ```
603
+
604
+ ### Cookie
481
605
 
482
606
  ---
483
607
 
484
- ### 浏览器工具 `browser`
608
+ #### setCookie(name, value, days?)
485
609
 
486
- #### URL 参数
610
+ > 设置 Cookie(默认7天)。
487
611
 
488
- - **`getUrlParams(url?)`** — 获取 URL 参数对象。
612
+ ```ts
613
+ setCookie("token", "abc123", 30);
614
+ ```
489
615
 
490
- ```ts
491
- getUrlParams('?a=1&b=2') // { a: '1', b: '2' }
492
- ```
616
+ #### getCookie(name)
493
617
 
494
- - **`getUrlParam(key, url?)`** 获取单个 URL 参数。
618
+ >获取 Cookie。
495
619
 
496
- ```ts
497
- getUrlParam('a') // "1"
498
- ```
620
+ ```ts
621
+ getCookie("token"); // "abc123"
622
+ ```
499
623
 
500
- - **`toQueryString(params)`** — 对象转 URL 参数字符串。
624
+ #### delCookie(name)
501
625
 
502
- ```ts
503
- toQueryString({ a: 1, b: 'hello' }) // "a=1&b=hello"
504
- ```
626
+ > — 删除 Cookie。
505
627
 
506
- #### 剪贴板与文件
628
+ ```ts
629
+ delCookie("token");
630
+ ```
507
631
 
508
- - **`copyToClipboard(text)`** — 复制文本到剪贴板(支持降级)。
632
+ ### 浏览器
509
633
 
510
- ```ts
511
- await copyToClipboard('Hello')
512
- ```
634
+ ---
513
635
 
514
- - **`downloadFile(content, filename, mimeType?)`** — 下载文件(Blob)。
636
+ #### getUrlParams(url?)
515
637
 
516
- ```ts
517
- downloadFile('Hello', 'hello.txt')
518
- ```
638
+ > — 获取 URL 参数对象。
519
639
 
520
- - **`exportJSON(data, filename?)`** — 导出 JSON 为文件。
640
+ ```ts
641
+ getUrlParams("?a=1&b=2"); // { a: '1', b: '2' }
642
+ ```
521
643
 
522
- ```ts
523
- exportJSON({ name: '张三' })
524
- ```
644
+ #### getUrlParam(key, url?)
525
645
 
526
- #### 页面滚动
646
+ > — 获取单个 URL 参数。
527
647
 
528
- - **`scrollToTop(behavior?)`** — 滚动到顶部(默认平滑)。
648
+ ```ts
649
+ getUrlParam("a"); // "1"
650
+ ```
529
651
 
530
- ```ts
531
- scrollToTop()
532
- ```
652
+ #### toQueryString(params)
533
653
 
534
- - **`scrollToBottom(behavior?)`** 滚动到底部(默认平滑)。
654
+ >对象转 URL 参数字符串。
535
655
 
536
- ```ts
537
- scrollToBottom()
538
- ```
656
+ ```ts
657
+ toQueryString({ a: 1, b: "hello" }); // "a=1&b=hello"
658
+ ```
539
659
 
540
- - **`onScroll(callback)`** — 监听滚动(rAF 节流),返回清理函数。
660
+ #### copyToClipboard(text)
541
661
 
542
- ```ts
543
- const off = onScroll(y => console.log(y))
544
- ```
662
+ > — 复制文本到剪贴板(支持降级)。
545
663
 
546
- #### 可视区域检测
664
+ ```ts
665
+ await copyToClipboard("Hello");
666
+ ```
547
667
 
548
- - **`observeIntersection(target, onEnter, onLeave?, options?)`** — 监听元素进入/离开可视区域,返回清理函数。
668
+ #### downloadFile(content, filename, mimeType?)
549
669
 
550
- ```ts
551
- const cleanup = observeIntersection(
552
- document.querySelector('.footer')!,
553
- () => loadMore(10),
554
- );
555
- ```
670
+ > — 下载文件(Blob)。
556
671
 
557
- ---
672
+ ```ts
673
+ downloadFile("Hello", "hello.txt");
674
+ ```
558
675
 
559
- ### 防抖与节流 — `control`
676
+ #### exportJSON(data, filename?)
560
677
 
561
- - **`debounce(fn, delay?, options?)`** 防抖,停止调用 delay 毫秒后才执行。
678
+ >导出 JSON 为文件。
562
679
 
563
- ```ts
564
- const fn = debounce((val: string) => console.log(val), 500)
565
- fn('a'); fn('b'); fn('c')
566
- // => 'c'
567
- ```
680
+ ```ts
681
+ exportJSON({ name: "张三" });
682
+ ```
568
683
 
569
- - **`throttle(fn, interval?, options?)`** — 节流,固定间隔内最多执行一次。
684
+ #### scrollToTop(behavior?)
570
685
 
571
- ```ts
572
- const fn = throttle((val: string) => console.log(val), 500)
573
- fn('a'); fn('b'); fn('c')
574
- // => 'a',500ms 后输出 'c'
575
- ```
686
+ > — 滚动到顶部(默认平滑)。
576
687
 
577
- ---
688
+ ```ts
689
+ scrollToTop();
690
+ ```
691
+
692
+ #### scrollToBottom(behavior?)
693
+
694
+ > — 滚动到底部(默认平滑)。
695
+
696
+ ```ts
697
+ scrollToBottom();
698
+ ```
699
+
700
+ #### onScroll(callback)
578
701
 
579
- ## 更新日志
702
+ > — 监听滚动(rAF 节流),返回清理函数。
703
+
704
+ ```ts
705
+ const off = onScroll((y) => console.log(y));
706
+ ```
580
707
 
581
- ### v1.0.7
708
+ #### observeIntersection(target, onEnter, onLeave?, options?)
582
709
 
583
- - **体积优化** 移除JSDoc `@example` 示例注释(共 294 行),减少包体积
584
- - **文档** — README 底部新增更新日志模块
710
+ >监听元素进入/离开可视区域,返回清理函数。
585
711
 
586
- ### v1.0.6
712
+ ```ts
713
+ const cleanup = observeIntersection(document.querySelector(".footer")!, () =>
714
+ loadMore(10),
715
+ );
716
+ ```
587
717
 
588
- - **数组模块** — 新增 `mergeArrays` 数组合并、`flatten` 数组扁平化(支持任意层级)、`arrFind` 数组项查询、`groupBy` JSON 数组分组、`filterEmptyValues` 对象移除空值属性、`createRange` 快速生成范围数组
589
- - **浏览器模块** — 新增 `observeIntersection` 可视区域检测(基于 IntersectionObserver)
718
+ ### 防抖与节流
590
719
 
591
- ### v1.0.5
720
+ ---
592
721
 
593
- - **控制模块** — 新增 `debounce` 防抖与 `throttle` 节流
722
+ #### debounce(fn, delay?, options?)
594
723
 
595
- ### v1.0.4
724
+ > — 防抖,停止调用 delay 毫秒后才执行。
596
725
 
597
- - 初始版本,包含以下模块:
598
- - **类型判断** `isArray` `isObject` `is` `isFunction` `isAsyncFunction` `isPromise` `isDate` `isNumber` `isInt` `isFloat` `isString` `isBoolean` `isSymbol` `isPrimitive` `isNull` `isDef` `isUnDef` `isNullOrUnDef` `isEmpty` `isEmptySv` `isEqual` `isHexColor` `isValidEmail` `isPC` `isWindow` `isElement` `isIOS` 共 27 个函数
599
- - **格式化** — 日期时间(`formatFull` `formatFullReplace` `formatYMD` `formatWeek`)、数字货币(`formatRmb` `formatNum` `percentCN` `compactEN` `compactCN` `signed`)、字符串(`maskPhone` `spacePhone` `capitalize` `kebabToCamel` `camelToKebab` `toCamel` `firstUpper` `firstLower` `reverse` `trimAll` `truncate` `truncateByWords`)共 22 个函数
600
- - **存储** — `localGet` `localSet` `localRm` `localClear` 共 4 个函数
601
- - **拷贝** — `deepClone` `deepCloneWithJSON` `shallowClone` 共 3 个函数
602
- - **数组** — `unique` `uniqueByKey` `sortNumAsc` `sortNumDesc` `sortByKey` `toArray` 共 6 个函数
603
- - **Cookie** — `setCookie` `getCookie` `delCookie` 共 3 个函数
604
- - **浏览器** — `getUrlParams` `getUrlParam` `toQueryString` `copyToClipboard` `downloadFile` `exportJSON` `scrollToTop` `scrollToBottom` `onScroll` 共 9 个函数
726
+ ```ts
727
+ const fn = debounce((val: string) => console.log(val), 500);
728
+ fn("a");
729
+ fn("b");
730
+ fn("c");
731
+ // => 'c'
732
+ ```
733
+
734
+ #### throttle(fn, interval?, options?)
735
+
736
+ > — 节流,固定间隔内最多执行一次。
737
+
738
+ ```ts
739
+ const fn = throttle((val: string) => console.log(val), 500);
740
+ fn("a");
741
+ fn("b");
742
+ fn("c");
743
+ // => 'a',500ms 后输出 'c'
744
+ ```