a2bei4-utils 1.0.0
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/LICENSE +21 -0
- package/README.md +2 -0
- package/dist/a2bei4.utils.cjs.js +1112 -0
- package/dist/a2bei4.utils.cjs.js.map +1 -0
- package/dist/a2bei4.utils.cjs.min.js +2 -0
- package/dist/a2bei4.utils.cjs.min.js.map +1 -0
- package/dist/a2bei4.utils.esm.js +1070 -0
- package/dist/a2bei4.utils.esm.js.map +1 -0
- package/dist/a2bei4.utils.esm.min.js +2 -0
- package/dist/a2bei4.utils.esm.min.js.map +1 -0
- package/dist/a2bei4.utils.umd.js +1118 -0
- package/dist/a2bei4.utils.umd.js.map +1 -0
- package/dist/a2bei4.utils.umd.min.js +2 -0
- package/dist/a2bei4.utils.umd.min.js.map +1 -0
- package/dist/arr.cjs +34 -0
- package/dist/arr.cjs.map +1 -0
- package/dist/arr.js +31 -0
- package/dist/arr.js.map +1 -0
- package/dist/browser.cjs +60 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.js +56 -0
- package/dist/browser.js.map +1 -0
- package/dist/common.cjs +391 -0
- package/dist/common.cjs.map +1 -0
- package/dist/common.js +373 -0
- package/dist/common.js.map +1 -0
- package/dist/date.cjs +195 -0
- package/dist/date.cjs.map +1 -0
- package/dist/date.js +188 -0
- package/dist/date.js.map +1 -0
- package/dist/download.cjs +70 -0
- package/dist/download.cjs.map +1 -0
- package/dist/download.js +64 -0
- package/dist/download.js.map +1 -0
- package/dist/evt.cjs +155 -0
- package/dist/evt.cjs.map +1 -0
- package/dist/evt.js +152 -0
- package/dist/evt.js.map +1 -0
- package/dist/id.cjs +75 -0
- package/dist/id.cjs.map +1 -0
- package/dist/id.js +72 -0
- package/dist/id.js.map +1 -0
- package/dist/timer.cjs +57 -0
- package/dist/timer.cjs.map +1 -0
- package/dist/timer.js +55 -0
- package/dist/timer.js.map +1 -0
- package/dist/tree.cjs +99 -0
- package/dist/tree.cjs.map +1 -0
- package/dist/tree.js +95 -0
- package/dist/tree.js.map +1 -0
- package/package.json +146 -0
- package/readme.txt +18 -0
- package/types/arr.d.ts +18 -0
- package/types/browser.d.ts +51 -0
- package/types/common.d.ts +170 -0
- package/types/date.d.ts +77 -0
- package/types/download.d.ts +39 -0
- package/types/evt.d.ts +52 -0
- package/types/id.d.ts +39 -0
- package/types/index.d.ts +499 -0
- package/types/timer.d.ts +32 -0
- package/types/tree.d.ts +30 -0
package/dist/common.cjs
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
//#region 数据类型判断
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* 返回任意值的运行时类型字符串(小写形式)。
|
|
7
|
+
*
|
|
8
|
+
* @param {*} obj 待检测的值
|
|
9
|
+
* @returns {keyof globalThis|"blob"|"file"|"formdata"|string} 小写类型名
|
|
10
|
+
*/
|
|
11
|
+
function getDataType(obj) {
|
|
12
|
+
return Object.prototype.toString
|
|
13
|
+
.call(obj)
|
|
14
|
+
.replace(/^\[object\s(\w+)\]$/, "$1")
|
|
15
|
+
.toLowerCase();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* 判断值是否为原生 Blob(含 File)。
|
|
20
|
+
*
|
|
21
|
+
* @param {*} obj - 待检测的值
|
|
22
|
+
* @returns {obj is Blob}
|
|
23
|
+
*/
|
|
24
|
+
function isBlob(obj) {
|
|
25
|
+
return getDataType(obj) === "blob";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* 判断值是否为**纯粹**的 Object(即 `{}` 或 `new Object()`,不含数组、null、自定义类等)。
|
|
30
|
+
*
|
|
31
|
+
* @param {*} obj - 待检测的值
|
|
32
|
+
* @returns {obj is Record<PropertyKey, any>}
|
|
33
|
+
*/
|
|
34
|
+
function isPlainObject(obj) {
|
|
35
|
+
return getDataType(obj) === "object";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* 判断值是否为 Promise(含 Promise 子类)。
|
|
40
|
+
*
|
|
41
|
+
* @param {*} obj - 待检测的值
|
|
42
|
+
* @returns {obj is Promise<any>}
|
|
43
|
+
*/
|
|
44
|
+
function isPromise(obj) {
|
|
45
|
+
return getDataType(obj) === "promise";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* 判断值是否为合法 Date 对象(含 Invalid Date 返回 false)。
|
|
50
|
+
*
|
|
51
|
+
* @param {*} t - 待检测值
|
|
52
|
+
* @returns {t is Date}
|
|
53
|
+
*/
|
|
54
|
+
function isDate(t) {
|
|
55
|
+
return getDataType(t) === "date";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 判断值是否为函数(含异步函数、生成器函数、类)。
|
|
60
|
+
*
|
|
61
|
+
* @param {*} obj - 待检测的值
|
|
62
|
+
* @returns {obj is Function}
|
|
63
|
+
*/
|
|
64
|
+
function isFunction(obj) {
|
|
65
|
+
return typeof obj === "function";
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* 判断值是否为**非空**字符串。
|
|
70
|
+
*
|
|
71
|
+
* @param {*} obj - 待检测的值
|
|
72
|
+
* @returns {obj is string}
|
|
73
|
+
*/
|
|
74
|
+
function isNonEmptyString(obj) {
|
|
75
|
+
return getDataType(obj) === "string" && obj.length > 0;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
|
|
80
|
+
//#region 随机数据
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* 在闭区间 [min, max] 内生成一个均匀分布的随机整数。
|
|
84
|
+
* 若 min > max 则自动交换。
|
|
85
|
+
*
|
|
86
|
+
* @param {number} min - 整数下界(包含)
|
|
87
|
+
* @param {number} max - 整数上界(包含)
|
|
88
|
+
* @returns {number}
|
|
89
|
+
* @throws {TypeError} 当 min 或 max 不是整数时抛出
|
|
90
|
+
*/
|
|
91
|
+
function randomIntInRange(min, max) {
|
|
92
|
+
if (!Number.isInteger(min) || !Number.isInteger(max)) {
|
|
93
|
+
throw new TypeError("Arguments must be integers");
|
|
94
|
+
}
|
|
95
|
+
if (min > max) [min, max] = [max, min];
|
|
96
|
+
// 注意加 1,否则 max 永远取不到;Math.floor 保证均匀
|
|
97
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* 随机生成一个汉字(可控制范围)。
|
|
102
|
+
*
|
|
103
|
+
* @param {boolean} [base=true] - 是否启用基本区(0x4E00-0x9FA5)
|
|
104
|
+
* @param {boolean} [extA=false] - 是否启用扩展 A 区(0x3400-0x4DBF)
|
|
105
|
+
* @param {boolean} [extBH=false] - 是否启用扩展 B~H 区(0x20000-0x2EBEF,代理对)
|
|
106
|
+
* @returns {string} 单个汉字字符
|
|
107
|
+
* @throws {RangeError} 未启用任何区段时抛出
|
|
108
|
+
*/
|
|
109
|
+
function randomHan(base = true, extA = false, extBH = false) {
|
|
110
|
+
// 1. 收集已启用的“区段”
|
|
111
|
+
const ranges = [];
|
|
112
|
+
if (base) ranges.push({ min: 0x4e00, max: 0x9fa5, surrogate: false });
|
|
113
|
+
if (extA) ranges.push({ min: 0x3400, max: 0x4dbf, surrogate: false });
|
|
114
|
+
if (extBH) ranges.push({ min: 0x20000, max: 0x2ebef, surrogate: true });
|
|
115
|
+
|
|
116
|
+
if (ranges.length === 0) {
|
|
117
|
+
throw new RangeError("At least one range must be enabled");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// 2. 按总码位数抽号
|
|
121
|
+
const total = ranges.reduce((sum, r) => sum + (r.max - r.min + 1), 0);
|
|
122
|
+
let n = randomIntInRange(0, total - 1);
|
|
123
|
+
|
|
124
|
+
// 3. 定位落在哪个区段
|
|
125
|
+
for (const { min, max, surrogate } of ranges) {
|
|
126
|
+
const size = max - min + 1;
|
|
127
|
+
if (n < size) {
|
|
128
|
+
const code = min + n;
|
|
129
|
+
if (!surrogate) return String.fromCharCode(code);
|
|
130
|
+
// 代理对
|
|
131
|
+
const offset = code - 0x10000;
|
|
132
|
+
const hi = (offset >> 10) + 0xd800;
|
|
133
|
+
const lo = (offset & 0x3ff) + 0xdc00;
|
|
134
|
+
return String.fromCharCode(hi, lo);
|
|
135
|
+
}
|
|
136
|
+
n -= size;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 随机生成一个英文字母。
|
|
142
|
+
*
|
|
143
|
+
* @param {'lower'|'upper'} [type] - 指定大小写;留空则随机
|
|
144
|
+
* @returns {string} 单个字母
|
|
145
|
+
*/
|
|
146
|
+
function randomEnLetter(type) {
|
|
147
|
+
const lower = "abcdefghijklmnopqrstuvwxyz";
|
|
148
|
+
const upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
149
|
+
const randomNum = randomIntInRange(0, 25);
|
|
150
|
+
|
|
151
|
+
switch (type) {
|
|
152
|
+
case "lower":
|
|
153
|
+
return lower[randomNum];
|
|
154
|
+
case "upper":
|
|
155
|
+
return upper[randomNum];
|
|
156
|
+
default:
|
|
157
|
+
return (Math.random() < 0.5 ? lower : upper)[randomNum];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* 生成指定长度的随机“中英混合”字符串。
|
|
163
|
+
*
|
|
164
|
+
* @param {number} [len=1] - 目标长度(≥1,自动取整)
|
|
165
|
+
* @param {number} [zhProb=0.5] - 每个位置选择汉字的概率,默认 0.5
|
|
166
|
+
* @returns {string}
|
|
167
|
+
*/
|
|
168
|
+
function randomHanOrEn(len, zhProb = 0.5) {
|
|
169
|
+
len = Math.max(1, Math.floor(len));
|
|
170
|
+
const buf = [];
|
|
171
|
+
for (let i = 0; i < len; i++) {
|
|
172
|
+
buf.push(Math.random() < zhProb ? randomHan() : randomEnLetter());
|
|
173
|
+
}
|
|
174
|
+
return buf.join("");
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
//#endregion
|
|
178
|
+
|
|
179
|
+
//#region 防抖节流
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 创建 debounced(防抖)函数。
|
|
183
|
+
* - 默认 trailing 触发;当 `leading=true` 时,首次调用或超过等待间隔会立即执行。
|
|
184
|
+
* - 支持手动取消。
|
|
185
|
+
*
|
|
186
|
+
* @template {(...args: any[]) => any} T
|
|
187
|
+
* @param {T} fn - 要防抖的原始函数
|
|
188
|
+
* @param {number} wait - 防抖等待时间(毫秒)
|
|
189
|
+
* @param {boolean} [leading=false] - 是否启用立即执行(leading edge)
|
|
190
|
+
* @returns {T & { cancel(): void }} 返回经过防抖包装的函数,并附带 `cancel` 方法
|
|
191
|
+
* @throws {TypeError} 当 `fn` 不是函数时抛出
|
|
192
|
+
*/
|
|
193
|
+
function debounce(fn, wait, leading = false) {
|
|
194
|
+
if (typeof fn !== "function") throw new TypeError("fn must be function");
|
|
195
|
+
wait = Math.max(0, Number(wait) || 0);
|
|
196
|
+
let timeoutId;
|
|
197
|
+
let lastCall = 0; // 0 表示从未调用过
|
|
198
|
+
|
|
199
|
+
function debounced(...args) {
|
|
200
|
+
const isFirst = lastCall === 0;
|
|
201
|
+
const isOverWait = Date.now() - lastCall >= wait;
|
|
202
|
+
|
|
203
|
+
clearTimeout(timeoutId);
|
|
204
|
+
|
|
205
|
+
// 首次调用 || 已达到等待间隔
|
|
206
|
+
if (leading && (isFirst || isOverWait)) {
|
|
207
|
+
lastCall = Date.now();
|
|
208
|
+
return fn.apply(this, args);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
timeoutId = setTimeout(() => {
|
|
212
|
+
lastCall = Date.now();
|
|
213
|
+
fn.apply(this, args);
|
|
214
|
+
}, wait);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
debounced.cancel = () => {
|
|
218
|
+
clearTimeout(timeoutId);
|
|
219
|
+
lastCall = 0; // 恢复初始状态
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
return debounced;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* 创建 throttled(节流)函数。
|
|
227
|
+
* 支持 leading/trailing 边缘触发,可手动取消。
|
|
228
|
+
*
|
|
229
|
+
* @template {(...args: any[]) => any} T
|
|
230
|
+
* @param {T} fn - 要节流的原始函数
|
|
231
|
+
* @param {number} wait - 节流间隔(毫秒)
|
|
232
|
+
* @param {object} [options] - 配置项
|
|
233
|
+
* @param {boolean} [options.leading=true] - 是否在 leading 边缘执行
|
|
234
|
+
* @param {boolean} [options.trailing=true] - 是否在 trailing 边缘执行
|
|
235
|
+
* @returns {T & { cancel(): void }} 返回经过节流包装的函数,并附带 `cancel` 方法
|
|
236
|
+
* @throws {TypeError} 当 `fn` 不是函数时抛出
|
|
237
|
+
*/
|
|
238
|
+
function throttle(fn, wait, { leading = true, trailing = true } = {}) {
|
|
239
|
+
if (typeof fn !== "function") throw new TypeError("fn must be function");
|
|
240
|
+
wait = Math.max(0, Number(wait) || 0);
|
|
241
|
+
|
|
242
|
+
let timeoutId = null,
|
|
243
|
+
lastCall = 0;
|
|
244
|
+
|
|
245
|
+
function throttled(...args) {
|
|
246
|
+
const remaining = wait - (Date.now() - lastCall);
|
|
247
|
+
|
|
248
|
+
if (leading && (lastCall === 0 || remaining <= 0)) {
|
|
249
|
+
lastCall = Date.now();
|
|
250
|
+
fn.apply(this, args);
|
|
251
|
+
} else if (trailing && !timeoutId) {
|
|
252
|
+
timeoutId = setTimeout(
|
|
253
|
+
() => {
|
|
254
|
+
timeoutId = null;
|
|
255
|
+
lastCall = Date.now();
|
|
256
|
+
fn.apply(this, args);
|
|
257
|
+
},
|
|
258
|
+
remaining > 0 ? remaining : wait
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
throttled.cancel = () => {
|
|
264
|
+
clearTimeout(timeoutId);
|
|
265
|
+
timeoutId = null;
|
|
266
|
+
lastCall = 0;
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
return throttled;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
//#endregion
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* 利用 JSON 序列化/反序列化实现**深拷贝**。
|
|
276
|
+
* 注意:会丢失 `undefined`、函数、循环引用、特殊包装对象等。
|
|
277
|
+
*
|
|
278
|
+
* @template T
|
|
279
|
+
* @param {T} obj - 待拷贝的 JSON 兼容值
|
|
280
|
+
* @returns {T} 深拷贝后的值
|
|
281
|
+
*/
|
|
282
|
+
function deepCloneByJSON(obj) {
|
|
283
|
+
return JSON.parse(JSON.stringify(obj));
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* **安全**地将源对象中**已存在**的属性赋值到目标对象。
|
|
288
|
+
* 不会新增键,也不会复制原型链上的属性。
|
|
289
|
+
*
|
|
290
|
+
* @template {Record<PropertyKey, any>} T
|
|
291
|
+
* @param {T} target - 目标对象(将被就地修改)
|
|
292
|
+
* @param {...Partial<T>} sources - 一个或多个源对象
|
|
293
|
+
* @returns {T} 修改后的目标对象(即第一个参数本身)
|
|
294
|
+
*
|
|
295
|
+
* @example
|
|
296
|
+
* const defaults = { a: 1, b: 2 };
|
|
297
|
+
* assignExisting(defaults, { a: 9, c: 99 }); // defaults 变为 { a: 9, b: 2 }
|
|
298
|
+
*/
|
|
299
|
+
function assignExisting(target, ...sources) {
|
|
300
|
+
sources.forEach((source) => {
|
|
301
|
+
Object.keys(source).forEach((key) => {
|
|
302
|
+
if (target.hasOwnProperty(key)) {
|
|
303
|
+
target[key] = source[key];
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
return target;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* 提取任意函数(含箭头函数、普通函数、async、class 构造器)的形参名称列表。
|
|
312
|
+
* 通过源码正则解析,不支持解构参数、默认参数、剩余参数等复杂语法;
|
|
313
|
+
* 若出现上述场景将返回空数组或部分名称。
|
|
314
|
+
*
|
|
315
|
+
* @param {Function} fn - 目标函数
|
|
316
|
+
* @returns {string[]} 按声明顺序排列的参数名数组;解析失败时返回空数组
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* getFunctionArgNames(function (a, b) {}) // ["a", "b"]
|
|
320
|
+
* getFunctionArgNames((foo, bar) => {}) // ["foo", "bar"]
|
|
321
|
+
* getFunctionArgNames(async function x({a} = {}) {}) // [] (解构无法识别)
|
|
322
|
+
*/
|
|
323
|
+
function getFunctionArgNames(fn) {
|
|
324
|
+
const FN_ARG_SPLIT = /,/,
|
|
325
|
+
FN_ARG = /^\s*(_?)(\S+?)\1\s*$/,
|
|
326
|
+
FN_ARGS = /^[^(]*\(\s*([^)]*)\)/m,
|
|
327
|
+
ARROW_ARG = /^([^(]+?)=>/,
|
|
328
|
+
STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
|
|
329
|
+
|
|
330
|
+
const fnText = Function.prototype.toString.call(fn).replace(STRIP_COMMENTS, "");
|
|
331
|
+
const argDecl = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);
|
|
332
|
+
const retArgNames = [];
|
|
333
|
+
[].forEach.call(argDecl[1].split(FN_ARG_SPLIT), function (arg) {
|
|
334
|
+
arg.replace(FN_ARG, function (all, underscore, name) {
|
|
335
|
+
retArgNames.push(name);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
return retArgNames;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* 将 Blob(或 File)读取为文本,并可选择自动执行 `JSON.parse`。
|
|
343
|
+
* 当 `isParse=true` 且内容非法 JSON 时,会回退为返回原始文本。
|
|
344
|
+
*
|
|
345
|
+
* @param {Blob} blob - 待读取的 Blob/File 对象
|
|
346
|
+
* @param {boolean} [isParse=true] - 是否尝试将结果按 JSON 解析
|
|
347
|
+
* @returns {Promise<string | any>} 解析后的 JSON 对象或原始文本
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* const json = await readBlobAsText(blob); // 自动 JSON.parse
|
|
351
|
+
* const text = await readBlobAsText(blob, false); // 仅返回文本
|
|
352
|
+
*/
|
|
353
|
+
function readBlobAsText(blob, isParse = true) {
|
|
354
|
+
return new Promise((resolve, reject) => {
|
|
355
|
+
const reader = new FileReader();
|
|
356
|
+
reader.onload = (evt) => {
|
|
357
|
+
const result = evt.target.result;
|
|
358
|
+
if (isParse) {
|
|
359
|
+
try {
|
|
360
|
+
resolve(JSON.parse(result));
|
|
361
|
+
} catch (error) {
|
|
362
|
+
console.error(error);
|
|
363
|
+
resolve(result);
|
|
364
|
+
}
|
|
365
|
+
} else {
|
|
366
|
+
resolve(result);
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
reader.onerror = reject;
|
|
370
|
+
reader.readAsText(blob);
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
exports.assignExisting = assignExisting;
|
|
375
|
+
exports.debounce = debounce;
|
|
376
|
+
exports.deepCloneByJSON = deepCloneByJSON;
|
|
377
|
+
exports.getDataType = getDataType;
|
|
378
|
+
exports.getFunctionArgNames = getFunctionArgNames;
|
|
379
|
+
exports.isBlob = isBlob;
|
|
380
|
+
exports.isDate = isDate;
|
|
381
|
+
exports.isFunction = isFunction;
|
|
382
|
+
exports.isNonEmptyString = isNonEmptyString;
|
|
383
|
+
exports.isPlainObject = isPlainObject;
|
|
384
|
+
exports.isPromise = isPromise;
|
|
385
|
+
exports.randomEnLetter = randomEnLetter;
|
|
386
|
+
exports.randomHan = randomHan;
|
|
387
|
+
exports.randomHanOrEn = randomHanOrEn;
|
|
388
|
+
exports.randomIntInRange = randomIntInRange;
|
|
389
|
+
exports.readBlobAsText = readBlobAsText;
|
|
390
|
+
exports.throttle = throttle;
|
|
391
|
+
//# sourceMappingURL=common.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.cjs","sources":["../src/source/common.js"],"sourcesContent":["//#region 数据类型判断\n\n/**\n * 返回任意值的运行时类型字符串(小写形式)。\n * \n * @param {*} obj 待检测的值\n * @returns {keyof globalThis|\"blob\"|\"file\"|\"formdata\"|string} 小写类型名\n */\nexport function getDataType(obj) {\n return Object.prototype.toString\n .call(obj)\n .replace(/^\\[object\\s(\\w+)\\]$/, \"$1\")\n .toLowerCase();\n}\n\n/**\n * 判断值是否为原生 Blob(含 File)。\n * \n * @param {*} obj - 待检测的值\n * @returns {obj is Blob}\n */\nexport function isBlob(obj) {\n return getDataType(obj) === \"blob\";\n}\n\n/**\n * 判断值是否为**纯粹**的 Object(即 `{}` 或 `new Object()`,不含数组、null、自定义类等)。\n * \n * @param {*} obj - 待检测的值\n * @returns {obj is Record<PropertyKey, any>}\n */\nexport function isPlainObject(obj) {\n return getDataType(obj) === \"object\";\n}\n\n/**\n * 判断值是否为 Promise(含 Promise 子类)。\n * \n * @param {*} obj - 待检测的值\n * @returns {obj is Promise<any>}\n */\nexport function isPromise(obj) {\n return getDataType(obj) === \"promise\";\n}\n\n/**\n * 判断值是否为合法 Date 对象(含 Invalid Date 返回 false)。\n *\n * @param {*} t - 待检测值\n * @returns {t is Date}\n */\nexport function isDate(t) {\n return getDataType(t) === \"date\";\n}\n\n/**\n * 判断值是否为函数(含异步函数、生成器函数、类)。\n * \n * @param {*} obj - 待检测的值\n * @returns {obj is Function}\n */\nexport function isFunction(obj) {\n return typeof obj === \"function\";\n}\n\n/**\n * 判断值是否为**非空**字符串。\n * \n * @param {*} obj - 待检测的值\n * @returns {obj is string}\n */\nexport function isNonEmptyString(obj) {\n return getDataType(obj) === \"string\" && obj.length > 0;\n}\n\n//#endregion\n\n//#region 随机数据\n\n/**\n * 在闭区间 [min, max] 内生成一个均匀分布的随机整数。\n * 若 min > max 则自动交换。\n *\n * @param {number} min - 整数下界(包含)\n * @param {number} max - 整数上界(包含)\n * @returns {number}\n * @throws {TypeError} 当 min 或 max 不是整数时抛出\n */\nexport function randomIntInRange(min, max) {\n if (!Number.isInteger(min) || !Number.isInteger(max)) {\n throw new TypeError(\"Arguments must be integers\");\n }\n if (min > max) [min, max] = [max, min];\n // 注意加 1,否则 max 永远取不到;Math.floor 保证均匀\n return Math.floor(Math.random() * (max - min + 1)) + min;\n}\n\n/**\n * 随机生成一个汉字(可控制范围)。\n *\n * @param {boolean} [base=true] - 是否启用基本区(0x4E00-0x9FA5)\n * @param {boolean} [extA=false] - 是否启用扩展 A 区(0x3400-0x4DBF)\n * @param {boolean} [extBH=false] - 是否启用扩展 B~H 区(0x20000-0x2EBEF,代理对)\n * @returns {string} 单个汉字字符\n * @throws {RangeError} 未启用任何区段时抛出\n */\nexport function randomHan(base = true, extA = false, extBH = false) {\n // 1. 收集已启用的“区段”\n const ranges = [];\n if (base) ranges.push({ min: 0x4e00, max: 0x9fa5, surrogate: false });\n if (extA) ranges.push({ min: 0x3400, max: 0x4dbf, surrogate: false });\n if (extBH) ranges.push({ min: 0x20000, max: 0x2ebef, surrogate: true });\n\n if (ranges.length === 0) {\n throw new RangeError(\"At least one range must be enabled\");\n }\n\n // 2. 按总码位数抽号\n const total = ranges.reduce((sum, r) => sum + (r.max - r.min + 1), 0);\n let n = randomIntInRange(0, total - 1);\n\n // 3. 定位落在哪个区段\n for (const { min, max, surrogate } of ranges) {\n const size = max - min + 1;\n if (n < size) {\n const code = min + n;\n if (!surrogate) return String.fromCharCode(code);\n // 代理对\n const offset = code - 0x10000;\n const hi = (offset >> 10) + 0xd800;\n const lo = (offset & 0x3ff) + 0xdc00;\n return String.fromCharCode(hi, lo);\n }\n n -= size;\n }\n}\n\n/**\n * 随机生成一个英文字母。\n *\n * @param {'lower'|'upper'} [type] - 指定大小写;留空则随机\n * @returns {string} 单个字母\n */\nexport function randomEnLetter(type) {\n const lower = \"abcdefghijklmnopqrstuvwxyz\";\n const upper = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\n const randomNum = randomIntInRange(0, 25);\n\n switch (type) {\n case \"lower\":\n return lower[randomNum];\n case \"upper\":\n return upper[randomNum];\n default:\n return (Math.random() < 0.5 ? lower : upper)[randomNum];\n }\n}\n\n/**\n * 生成指定长度的随机“中英混合”字符串。\n *\n * @param {number} [len=1] - 目标长度(≥1,自动取整)\n * @param {number} [zhProb=0.5] - 每个位置选择汉字的概率,默认 0.5\n * @returns {string}\n */\nexport function randomHanOrEn(len, zhProb = 0.5) {\n len = Math.max(1, Math.floor(len));\n const buf = [];\n for (let i = 0; i < len; i++) {\n buf.push(Math.random() < zhProb ? randomHan() : randomEnLetter());\n }\n return buf.join(\"\");\n}\n\n//#endregion\n\n//#region 防抖节流\n\n/**\n * 创建 debounced(防抖)函数。\n * - 默认 trailing 触发;当 `leading=true` 时,首次调用或超过等待间隔会立即执行。\n * - 支持手动取消。\n *\n * @template {(...args: any[]) => any} T\n * @param {T} fn - 要防抖的原始函数\n * @param {number} wait - 防抖等待时间(毫秒)\n * @param {boolean} [leading=false] - 是否启用立即执行(leading edge)\n * @returns {T & { cancel(): void }} 返回经过防抖包装的函数,并附带 `cancel` 方法\n * @throws {TypeError} 当 `fn` 不是函数时抛出\n */\nexport function debounce(fn, wait, leading = false) {\n if (typeof fn !== \"function\") throw new TypeError(\"fn must be function\");\n wait = Math.max(0, Number(wait) || 0);\n let timeoutId;\n let lastCall = 0; // 0 表示从未调用过\n\n function debounced(...args) {\n const isFirst = lastCall === 0;\n const isOverWait = Date.now() - lastCall >= wait;\n\n clearTimeout(timeoutId);\n\n // 首次调用 || 已达到等待间隔\n if (leading && (isFirst || isOverWait)) {\n lastCall = Date.now();\n return fn.apply(this, args);\n }\n\n timeoutId = setTimeout(() => {\n lastCall = Date.now();\n fn.apply(this, args);\n }, wait);\n }\n\n debounced.cancel = () => {\n clearTimeout(timeoutId);\n lastCall = 0; // 恢复初始状态\n };\n\n return debounced;\n}\n\n/**\n * 创建 throttled(节流)函数。\n * 支持 leading/trailing 边缘触发,可手动取消。\n *\n * @template {(...args: any[]) => any} T\n * @param {T} fn - 要节流的原始函数\n * @param {number} wait - 节流间隔(毫秒)\n * @param {object} [options] - 配置项\n * @param {boolean} [options.leading=true] - 是否在 leading 边缘执行\n * @param {boolean} [options.trailing=true] - 是否在 trailing 边缘执行\n * @returns {T & { cancel(): void }} 返回经过节流包装的函数,并附带 `cancel` 方法\n * @throws {TypeError} 当 `fn` 不是函数时抛出\n */\nexport function throttle(fn, wait, { leading = true, trailing = true } = {}) {\n if (typeof fn !== \"function\") throw new TypeError(\"fn must be function\");\n wait = Math.max(0, Number(wait) || 0);\n\n let timeoutId = null,\n lastCall = 0;\n\n function throttled(...args) {\n const remaining = wait - (Date.now() - lastCall);\n\n if (leading && (lastCall === 0 || remaining <= 0)) {\n lastCall = Date.now();\n fn.apply(this, args);\n } else if (trailing && !timeoutId) {\n timeoutId = setTimeout(\n () => {\n timeoutId = null;\n lastCall = Date.now();\n fn.apply(this, args);\n },\n remaining > 0 ? remaining : wait\n );\n }\n }\n\n throttled.cancel = () => {\n clearTimeout(timeoutId);\n timeoutId = null;\n lastCall = 0;\n };\n\n return throttled;\n}\n\n//#endregion\n\n/**\n * 利用 JSON 序列化/反序列化实现**深拷贝**。\n * 注意:会丢失 `undefined`、函数、循环引用、特殊包装对象等。\n *\n * @template T\n * @param {T} obj - 待拷贝的 JSON 兼容值\n * @returns {T} 深拷贝后的值\n */\nexport function deepCloneByJSON(obj) {\n return JSON.parse(JSON.stringify(obj));\n}\n\n/**\n * **安全**地将源对象中**已存在**的属性赋值到目标对象。\n * 不会新增键,也不会复制原型链上的属性。\n *\n * @template {Record<PropertyKey, any>} T\n * @param {T} target - 目标对象(将被就地修改)\n * @param {...Partial<T>} sources - 一个或多个源对象\n * @returns {T} 修改后的目标对象(即第一个参数本身)\n *\n * @example\n * const defaults = { a: 1, b: 2 };\n * assignExisting(defaults, { a: 9, c: 99 }); // defaults 变为 { a: 9, b: 2 }\n */\nexport function assignExisting(target, ...sources) {\n sources.forEach((source) => {\n Object.keys(source).forEach((key) => {\n if (target.hasOwnProperty(key)) {\n target[key] = source[key];\n }\n });\n });\n return target;\n}\n\n/**\n * 提取任意函数(含箭头函数、普通函数、async、class 构造器)的形参名称列表。\n * 通过源码正则解析,不支持解构参数、默认参数、剩余参数等复杂语法;\n * 若出现上述场景将返回空数组或部分名称。\n *\n * @param {Function} fn - 目标函数\n * @returns {string[]} 按声明顺序排列的参数名数组;解析失败时返回空数组\n *\n * @example\n * getFunctionArgNames(function (a, b) {}) // [\"a\", \"b\"]\n * getFunctionArgNames((foo, bar) => {}) // [\"foo\", \"bar\"]\n * getFunctionArgNames(async function x({a} = {}) {}) // [] (解构无法识别)\n */\nexport function getFunctionArgNames(fn) {\n const FN_ARG_SPLIT = /,/,\n FN_ARG = /^\\s*(_?)(\\S+?)\\1\\s*$/,\n FN_ARGS = /^[^(]*\\(\\s*([^)]*)\\)/m,\n ARROW_ARG = /^([^(]+?)=>/,\n STRIP_COMMENTS = /((\\/\\/.*$)|(\\/\\*[\\s\\S]*?\\*\\/))/gm;\n\n const fnText = Function.prototype.toString.call(fn).replace(STRIP_COMMENTS, \"\");\n const argDecl = fnText.match(ARROW_ARG) || fnText.match(FN_ARGS);\n const retArgNames = [];\n [].forEach.call(argDecl[1].split(FN_ARG_SPLIT), function (arg) {\n arg.replace(FN_ARG, function (all, underscore, name) {\n retArgNames.push(name);\n });\n });\n return retArgNames;\n}\n\n/**\n * 将 Blob(或 File)读取为文本,并可选择自动执行 `JSON.parse`。\n * 当 `isParse=true` 且内容非法 JSON 时,会回退为返回原始文本。\n *\n * @param {Blob} blob - 待读取的 Blob/File 对象\n * @param {boolean} [isParse=true] - 是否尝试将结果按 JSON 解析\n * @returns {Promise<string | any>} 解析后的 JSON 对象或原始文本\n *\n * @example\n * const json = await readBlobAsText(blob); // 自动 JSON.parse\n * const text = await readBlobAsText(blob, false); // 仅返回文本\n */\nexport function readBlobAsText(blob, isParse = true) {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onload = (evt) => {\n const result = evt.target.result;\n if (isParse) {\n try {\n resolve(JSON.parse(result));\n } catch (error) {\n console.error(error);\n resolve(result);\n }\n } else {\n resolve(result);\n }\n };\n reader.onerror = reject;\n reader.readAsText(blob);\n });\n}\n"],"names":[],"mappings":"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"}
|