sculp-js 1.8.2 → 1.8.4
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/lib/cjs/array.js +2 -3
- package/lib/cjs/async.js +1 -1
- package/lib/cjs/base64.js +1 -1
- package/lib/cjs/clipboard.js +1 -1
- package/lib/cjs/cloneDeep.js +117 -0
- package/lib/cjs/cookie.js +1 -1
- package/lib/cjs/date.js +1 -1
- package/lib/cjs/dom.js +1 -1
- package/lib/cjs/download.js +29 -5
- package/lib/cjs/easing.js +1 -1
- package/lib/cjs/file.js +1 -1
- package/lib/cjs/func.js +1 -28
- package/lib/cjs/index.js +5 -3
- package/lib/cjs/isEqual.js +133 -0
- package/lib/cjs/math.js +1 -1
- package/lib/cjs/number.js +1 -1
- package/lib/cjs/object.js +1 -235
- package/lib/cjs/path.js +1 -1
- package/lib/cjs/qs.js +1 -1
- package/lib/cjs/random.js +1 -1
- package/lib/cjs/string.js +1 -1
- package/lib/cjs/tooltip.js +1 -1
- package/lib/cjs/tree.js +1 -1
- package/lib/cjs/type.js +1 -1
- package/lib/cjs/unique.js +1 -1
- package/lib/cjs/url.js +1 -1
- package/lib/cjs/validator.js +1 -1
- package/lib/cjs/variable.js +3 -2
- package/lib/cjs/watermark.js +1 -1
- package/lib/cjs/we-decode.js +1 -1
- package/lib/es/array.js +2 -3
- package/lib/es/async.js +1 -1
- package/lib/es/base64.js +1 -1
- package/lib/es/clipboard.js +1 -1
- package/lib/es/cloneDeep.js +115 -0
- package/lib/es/cookie.js +1 -1
- package/lib/es/date.js +1 -1
- package/lib/es/dom.js +1 -1
- package/lib/es/download.js +30 -6
- package/lib/es/easing.js +1 -1
- package/lib/es/file.js +1 -1
- package/lib/es/func.js +1 -28
- package/lib/es/index.js +4 -2
- package/lib/es/isEqual.js +131 -0
- package/lib/es/math.js +1 -1
- package/lib/es/number.js +1 -1
- package/lib/es/object.js +2 -234
- package/lib/es/path.js +1 -1
- package/lib/es/qs.js +1 -1
- package/lib/es/random.js +1 -1
- package/lib/es/string.js +1 -1
- package/lib/es/tooltip.js +1 -1
- package/lib/es/tree.js +1 -1
- package/lib/es/type.js +1 -1
- package/lib/es/unique.js +1 -1
- package/lib/es/url.js +1 -1
- package/lib/es/validator.js +1 -1
- package/lib/es/variable.js +4 -3
- package/lib/es/watermark.js +1 -1
- package/lib/es/we-decode.js +1 -1
- package/lib/index.d.ts +32 -21
- package/lib/umd/index.js +262 -267
- package/package.json +1 -1
package/lib/umd/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* sculp-js v1.8.
|
|
2
|
+
* sculp-js v1.8.4
|
|
3
3
|
* (c) 2023-present chandq
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -72,7 +72,6 @@
|
|
|
72
72
|
function arrayInsertBefore(array, start, to) {
|
|
73
73
|
if (start === to || start + 1 === to)
|
|
74
74
|
return;
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
76
75
|
const [source] = array.splice(start, 1);
|
|
77
76
|
const insertIndex = to < start ? to : to - 1;
|
|
78
77
|
array.splice(insertIndex, 0, source);
|
|
@@ -92,7 +91,7 @@
|
|
|
92
91
|
if (_expect(val, idx))
|
|
93
92
|
indexes.push(idx);
|
|
94
93
|
});
|
|
95
|
-
|
|
94
|
+
indexes.forEach((val, idx) => {
|
|
96
95
|
array.splice(val - idx, 1);
|
|
97
96
|
});
|
|
98
97
|
return array;
|
|
@@ -294,7 +293,6 @@
|
|
|
294
293
|
for (const key in obj) {
|
|
295
294
|
if (!objectHas(obj, key))
|
|
296
295
|
continue;
|
|
297
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
298
296
|
obj2[key] = iterator(obj[key], key);
|
|
299
297
|
}
|
|
300
298
|
return obj2;
|
|
@@ -309,7 +307,6 @@
|
|
|
309
307
|
const obj2 = {};
|
|
310
308
|
objectEach(obj, (v, k) => {
|
|
311
309
|
if (keys.includes(k)) {
|
|
312
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
313
310
|
// @ts-ignore
|
|
314
311
|
obj2[k] = v;
|
|
315
312
|
}
|
|
@@ -326,7 +323,6 @@
|
|
|
326
323
|
const obj2 = {};
|
|
327
324
|
objectEach(obj, (v, k) => {
|
|
328
325
|
if (!keys.includes(k)) {
|
|
329
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
330
326
|
// @ts-ignore
|
|
331
327
|
obj2[k] = v;
|
|
332
328
|
}
|
|
@@ -379,7 +375,6 @@
|
|
|
379
375
|
const map = new Map();
|
|
380
376
|
for (let i = 0, len = targets.length; i < len; i++) {
|
|
381
377
|
const target = targets[i];
|
|
382
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
383
378
|
// @ts-ignore
|
|
384
379
|
source = merge(map, source, target);
|
|
385
380
|
}
|
|
@@ -437,234 +432,6 @@
|
|
|
437
432
|
v: tempObj ? tempObj[keyArr[i]] : undefined
|
|
438
433
|
};
|
|
439
434
|
}
|
|
440
|
-
/**
|
|
441
|
-
* 深拷贝堪称完全体 即:任何类型的数据都会被深拷贝
|
|
442
|
-
*
|
|
443
|
-
* 包含对null、原始值、对象循环引用的处理
|
|
444
|
-
*
|
|
445
|
-
* 对Map、Set、ArrayBuffer、Date、RegExp、Array、Object及原型链属性方法执行深拷贝
|
|
446
|
-
* @param {T} source
|
|
447
|
-
* @param {WeakMap} map
|
|
448
|
-
* @returns {T}
|
|
449
|
-
*/
|
|
450
|
-
function cloneDeep(source, map = new WeakMap()) {
|
|
451
|
-
// 处理原始类型和 null/undefined
|
|
452
|
-
if (source === null || typeof source !== 'object') {
|
|
453
|
-
return source;
|
|
454
|
-
}
|
|
455
|
-
// 处理循环引用
|
|
456
|
-
if (map.has(source)) {
|
|
457
|
-
return map.get(source);
|
|
458
|
-
}
|
|
459
|
-
// 处理 ArrayBuffer
|
|
460
|
-
if (source instanceof ArrayBuffer) {
|
|
461
|
-
const copy = new ArrayBuffer(source.byteLength);
|
|
462
|
-
new Uint8Array(copy).set(new Uint8Array(source));
|
|
463
|
-
map.set(source, copy);
|
|
464
|
-
return copy;
|
|
465
|
-
}
|
|
466
|
-
// 处理 DataView 和 TypedArray (Uint8Array 等)
|
|
467
|
-
if (ArrayBuffer.isView(source)) {
|
|
468
|
-
const constructor = source.constructor;
|
|
469
|
-
const bufferCopy = cloneDeep(source.buffer, map);
|
|
470
|
-
return new constructor(bufferCopy, source.byteOffset, source.length);
|
|
471
|
-
}
|
|
472
|
-
// 处理 Date 对象
|
|
473
|
-
if (source instanceof Date) {
|
|
474
|
-
const copy = new Date(source.getTime());
|
|
475
|
-
map.set(source, copy);
|
|
476
|
-
return copy;
|
|
477
|
-
}
|
|
478
|
-
// 处理 RegExp 对象
|
|
479
|
-
if (source instanceof RegExp) {
|
|
480
|
-
const copy = new RegExp(source.source, source.flags);
|
|
481
|
-
copy.lastIndex = source.lastIndex; // 保留匹配状态
|
|
482
|
-
map.set(source, copy);
|
|
483
|
-
return copy;
|
|
484
|
-
}
|
|
485
|
-
// 处理 Map
|
|
486
|
-
if (source instanceof Map) {
|
|
487
|
-
const copy = new Map();
|
|
488
|
-
map.set(source, copy);
|
|
489
|
-
source.forEach((value, key) => {
|
|
490
|
-
copy.set(cloneDeep(key, map), cloneDeep(value, map));
|
|
491
|
-
});
|
|
492
|
-
return copy;
|
|
493
|
-
}
|
|
494
|
-
// 处理 Set
|
|
495
|
-
if (source instanceof Set) {
|
|
496
|
-
const copy = new Set();
|
|
497
|
-
map.set(source, copy);
|
|
498
|
-
source.forEach(value => {
|
|
499
|
-
copy.add(cloneDeep(value, map));
|
|
500
|
-
});
|
|
501
|
-
return copy;
|
|
502
|
-
}
|
|
503
|
-
// 处理数组 (包含稀疏数组)
|
|
504
|
-
if (Array.isArray(source)) {
|
|
505
|
-
const copy = new Array(source.length);
|
|
506
|
-
map.set(source, copy);
|
|
507
|
-
// 克隆所有有效索引
|
|
508
|
-
for (let i = 0, len = source.length; i < len; i++) {
|
|
509
|
-
if (i in source) {
|
|
510
|
-
// 保留空位
|
|
511
|
-
copy[i] = cloneDeep(source[i], map);
|
|
512
|
-
}
|
|
513
|
-
}
|
|
514
|
-
// 克隆数组的自定义属性
|
|
515
|
-
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
516
|
-
for (const key of Reflect.ownKeys(descriptors)) {
|
|
517
|
-
Object.defineProperty(copy, key, {
|
|
518
|
-
...descriptors[key],
|
|
519
|
-
value: cloneDeep(descriptors[key].value, map)
|
|
520
|
-
});
|
|
521
|
-
}
|
|
522
|
-
return copy;
|
|
523
|
-
}
|
|
524
|
-
// 处理普通对象和类实例
|
|
525
|
-
const copy = Object.create(Object.getPrototypeOf(source));
|
|
526
|
-
map.set(source, copy);
|
|
527
|
-
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
528
|
-
for (const key of Reflect.ownKeys(descriptors)) {
|
|
529
|
-
const descriptor = descriptors[key];
|
|
530
|
-
if ('value' in descriptor) {
|
|
531
|
-
// 克隆数据属性
|
|
532
|
-
descriptor.value = cloneDeep(descriptor.value, map);
|
|
533
|
-
}
|
|
534
|
-
else {
|
|
535
|
-
// 处理访问器属性 (getter/setter)
|
|
536
|
-
if (descriptor.get) {
|
|
537
|
-
descriptor.get = cloneDeep(descriptor.get, map);
|
|
538
|
-
}
|
|
539
|
-
if (descriptor.set) {
|
|
540
|
-
descriptor.set = cloneDeep(descriptor.set, map);
|
|
541
|
-
}
|
|
542
|
-
}
|
|
543
|
-
Object.defineProperty(copy, key, descriptor);
|
|
544
|
-
}
|
|
545
|
-
return copy;
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* 比较两值是否相等,适用所有数据类型
|
|
549
|
-
* @param {Comparable} a
|
|
550
|
-
* @param {Comparable} b
|
|
551
|
-
* @returns {boolean}
|
|
552
|
-
*/
|
|
553
|
-
function isEqual(a, b) {
|
|
554
|
-
return deepEqual(a, b);
|
|
555
|
-
}
|
|
556
|
-
function deepEqual(a, b, compared = new WeakMap()) {
|
|
557
|
-
// 相同值快速返回
|
|
558
|
-
if (Object.is(a, b))
|
|
559
|
-
return true;
|
|
560
|
-
// 类型不同直接返回false
|
|
561
|
-
const typeA = Object.prototype.toString.call(a);
|
|
562
|
-
const typeB = Object.prototype.toString.call(b);
|
|
563
|
-
if (typeA !== typeB)
|
|
564
|
-
return false;
|
|
565
|
-
// 只缓存对象类型
|
|
566
|
-
if (isObject(a) && isObject(b)) {
|
|
567
|
-
if (compared.has(a))
|
|
568
|
-
return compared.get(a) === b;
|
|
569
|
-
compared.set(a, b);
|
|
570
|
-
compared.set(b, a);
|
|
571
|
-
}
|
|
572
|
-
// 处理特殊对象类型
|
|
573
|
-
switch (typeA) {
|
|
574
|
-
case '[object Date]':
|
|
575
|
-
return a.getTime() === b.getTime();
|
|
576
|
-
case '[object RegExp]':
|
|
577
|
-
return a.toString() === b.toString();
|
|
578
|
-
case '[object Map]':
|
|
579
|
-
return compareMap(a, b, compared);
|
|
580
|
-
case '[object Set]':
|
|
581
|
-
return compareSet(a, b, compared);
|
|
582
|
-
case '[object ArrayBuffer]':
|
|
583
|
-
return compareArrayBuffer(a, b);
|
|
584
|
-
case '[object DataView]':
|
|
585
|
-
return compareDataView(a, b, compared);
|
|
586
|
-
case '[object Int8Array]':
|
|
587
|
-
case '[object Uint8Array]':
|
|
588
|
-
case '[object Uint8ClampedArray]':
|
|
589
|
-
case '[object Int16Array]':
|
|
590
|
-
case '[object Uint16Array]':
|
|
591
|
-
case '[object Int32Array]':
|
|
592
|
-
case '[object Uint32Array]':
|
|
593
|
-
case '[object Float32Array]':
|
|
594
|
-
case '[object Float64Array]':
|
|
595
|
-
return compareTypedArray(a, b, compared);
|
|
596
|
-
case '[object Object]':
|
|
597
|
-
return compareObjects(a, b, compared);
|
|
598
|
-
case '[object Array]':
|
|
599
|
-
return compareArrays(a, b, compared);
|
|
600
|
-
}
|
|
601
|
-
return false;
|
|
602
|
-
}
|
|
603
|
-
// 辅助比较函数
|
|
604
|
-
function compareMap(a, b, compared) {
|
|
605
|
-
if (a.size !== b.size)
|
|
606
|
-
return false;
|
|
607
|
-
for (const [key, value] of a) {
|
|
608
|
-
if (!b.has(key) || !deepEqual(value, b.get(key), compared))
|
|
609
|
-
return false;
|
|
610
|
-
}
|
|
611
|
-
return true;
|
|
612
|
-
}
|
|
613
|
-
function compareSet(a, b, compared) {
|
|
614
|
-
if (a.size !== b.size)
|
|
615
|
-
return false;
|
|
616
|
-
for (const value of a) {
|
|
617
|
-
let found = false;
|
|
618
|
-
for (const bValue of b) {
|
|
619
|
-
if (deepEqual(value, bValue, compared)) {
|
|
620
|
-
found = true;
|
|
621
|
-
break;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
624
|
-
if (!found)
|
|
625
|
-
return false;
|
|
626
|
-
}
|
|
627
|
-
return true;
|
|
628
|
-
}
|
|
629
|
-
function compareArrayBuffer(a, b) {
|
|
630
|
-
if (a.byteLength !== b.byteLength)
|
|
631
|
-
return false;
|
|
632
|
-
return new DataView(a).getInt32(0) === new DataView(b).getInt32(0);
|
|
633
|
-
}
|
|
634
|
-
function compareDataView(a, b, compared) {
|
|
635
|
-
return a.byteLength === b.byteLength && deepEqual(new Uint8Array(a.buffer), new Uint8Array(b.buffer), compared);
|
|
636
|
-
}
|
|
637
|
-
function compareTypedArray(a, b, compared) {
|
|
638
|
-
return a.byteLength === b.byteLength && deepEqual(Array.from(a), Array.from(b), compared);
|
|
639
|
-
}
|
|
640
|
-
function compareObjects(a, b, compared) {
|
|
641
|
-
const keysA = Reflect.ownKeys(a);
|
|
642
|
-
const keysB = Reflect.ownKeys(b);
|
|
643
|
-
if (keysA.length !== keysB.length)
|
|
644
|
-
return false;
|
|
645
|
-
for (const key of keysA) {
|
|
646
|
-
if (!keysB.includes(key))
|
|
647
|
-
return false;
|
|
648
|
-
if (!deepEqual(a[key], b[key], compared))
|
|
649
|
-
return false;
|
|
650
|
-
}
|
|
651
|
-
// 原型链比较
|
|
652
|
-
return Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
|
|
653
|
-
}
|
|
654
|
-
function compareArrays(a, b, compared) {
|
|
655
|
-
// 增加有效索引检查
|
|
656
|
-
const keysA = Object.keys(a).map(Number);
|
|
657
|
-
const keysB = Object.keys(b).map(Number);
|
|
658
|
-
if (keysA.length !== keysB.length)
|
|
659
|
-
return false;
|
|
660
|
-
// 递归比较每个元素
|
|
661
|
-
for (let i = 0, len = a.length; i < len; i++) {
|
|
662
|
-
if (!deepEqual(a[i], b[i], compared))
|
|
663
|
-
return false;
|
|
664
|
-
}
|
|
665
|
-
// 比较数组对象的其他属性
|
|
666
|
-
return compareObjects(a, b, compared);
|
|
667
|
-
}
|
|
668
435
|
|
|
669
436
|
/**
|
|
670
437
|
* 将字符串转换为驼峰格式
|
|
@@ -1455,17 +1222,41 @@
|
|
|
1455
1222
|
}
|
|
1456
1223
|
/**
|
|
1457
1224
|
* 根据URL下载文件(解决跨域a.download不生效问题)
|
|
1225
|
+
*
|
|
1226
|
+
* 可定制下载成功的状态码status(浏览器原生状态码)
|
|
1227
|
+
*
|
|
1228
|
+
* 支持下载操作成功、失败后的回调
|
|
1458
1229
|
* @param {string} url
|
|
1459
1230
|
* @param {string} filename
|
|
1460
|
-
* @param {
|
|
1231
|
+
* @param {CrossOriginDownloadParams} options
|
|
1461
1232
|
*/
|
|
1462
|
-
function crossOriginDownload(url, filename,
|
|
1233
|
+
function crossOriginDownload(url, filename, options) {
|
|
1234
|
+
const { successCode = 200, successCallback, failCallback } = isNullOrUnDef(options) ? { successCode: 200, successCallback: void 0, failCallback: void 0 } : options;
|
|
1463
1235
|
const xhr = new XMLHttpRequest();
|
|
1464
1236
|
xhr.open('GET', url, true);
|
|
1465
1237
|
xhr.responseType = 'blob';
|
|
1466
1238
|
xhr.onload = function () {
|
|
1467
|
-
if (xhr.status ===
|
|
1468
|
-
downloadBlob(xhr.response, filename,
|
|
1239
|
+
if (xhr.status === successCode)
|
|
1240
|
+
downloadBlob(xhr.response, filename, successCallback);
|
|
1241
|
+
else if (isFunction(failCallback)) {
|
|
1242
|
+
const status = xhr.status;
|
|
1243
|
+
const responseType = xhr.getResponseHeader('Content-Type');
|
|
1244
|
+
if (isString(responseType) && responseType.includes('application/json')) {
|
|
1245
|
+
const reader = new FileReader();
|
|
1246
|
+
reader.onload = () => {
|
|
1247
|
+
failCallback({ status, response: reader.result });
|
|
1248
|
+
};
|
|
1249
|
+
reader.readAsText(xhr.response);
|
|
1250
|
+
}
|
|
1251
|
+
else {
|
|
1252
|
+
failCallback(xhr);
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
xhr.onerror = e => {
|
|
1257
|
+
if (isFunction(failCallback)) {
|
|
1258
|
+
failCallback({ status: 0, code: 'ERROR_CONNECTION_REFUSED' });
|
|
1259
|
+
}
|
|
1469
1260
|
};
|
|
1470
1261
|
xhr.send();
|
|
1471
1262
|
}
|
|
@@ -1958,13 +1749,10 @@
|
|
|
1958
1749
|
let called = false;
|
|
1959
1750
|
let result;
|
|
1960
1751
|
return function (...args) {
|
|
1961
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
1962
1752
|
if (called)
|
|
1963
1753
|
return result;
|
|
1964
1754
|
called = true;
|
|
1965
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1966
1755
|
result = func.call(this, ...args);
|
|
1967
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
1968
1756
|
return result;
|
|
1969
1757
|
};
|
|
1970
1758
|
};
|
|
@@ -1974,24 +1762,12 @@
|
|
|
1974
1762
|
* @param val
|
|
1975
1763
|
*/
|
|
1976
1764
|
function setGlobal(key, val) {
|
|
1977
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1978
|
-
// @ts-ignore
|
|
1979
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1980
1765
|
if (typeof globalThis !== 'undefined')
|
|
1981
1766
|
globalThis[key] = val;
|
|
1982
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1983
|
-
// @ts-ignore
|
|
1984
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1985
1767
|
else if (typeof window !== 'undefined')
|
|
1986
1768
|
window[key] = val;
|
|
1987
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1988
|
-
// @ts-ignore
|
|
1989
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1990
1769
|
else if (typeof global !== 'undefined')
|
|
1991
1770
|
global[key] = val;
|
|
1992
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
1993
|
-
// @ts-ignore
|
|
1994
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
1995
1771
|
else if (typeof self !== 'undefined')
|
|
1996
1772
|
self[key] = val;
|
|
1997
1773
|
else
|
|
@@ -2003,24 +1779,12 @@
|
|
|
2003
1779
|
* @param val
|
|
2004
1780
|
*/
|
|
2005
1781
|
function getGlobal(key) {
|
|
2006
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2007
|
-
// @ts-ignore
|
|
2008
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
2009
1782
|
if (typeof globalThis !== 'undefined')
|
|
2010
1783
|
return globalThis[key];
|
|
2011
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2012
|
-
// @ts-ignore
|
|
2013
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
2014
1784
|
else if (typeof window !== 'undefined')
|
|
2015
1785
|
return window[key];
|
|
2016
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2017
|
-
// @ts-ignore
|
|
2018
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
2019
1786
|
else if (typeof global !== 'undefined')
|
|
2020
1787
|
return global[key];
|
|
2021
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
2022
|
-
// @ts-ignore
|
|
2023
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
2024
1788
|
else if (typeof self !== 'undefined')
|
|
2025
1789
|
return self[key];
|
|
2026
1790
|
}
|
|
@@ -2889,7 +2653,8 @@
|
|
|
2889
2653
|
* default match symbol {} same as /{\s*([^{}\s]*)\s*}/g
|
|
2890
2654
|
*/
|
|
2891
2655
|
function parseVarFromString(str, leftMatchSymbol = '{', rightMatchSymbol = '}') {
|
|
2892
|
-
|
|
2656
|
+
// @ts-ignore
|
|
2657
|
+
return Array.from(str.matchAll(parseVariableRegExp(leftMatchSymbol, rightMatchSymbol))).map(el => isNullOrUnDef(el) ? void 0 : el[1]);
|
|
2893
2658
|
}
|
|
2894
2659
|
/**
|
|
2895
2660
|
* 替换字符串中的插值变量
|
|
@@ -2951,6 +2716,236 @@
|
|
|
2951
2716
|
}
|
|
2952
2717
|
}
|
|
2953
2718
|
|
|
2719
|
+
/**
|
|
2720
|
+
* 深拷贝堪称完全体 即:任何类型的数据都会被深拷贝
|
|
2721
|
+
*
|
|
2722
|
+
* 包含对null、原始值、对象循环引用的处理
|
|
2723
|
+
*
|
|
2724
|
+
* 对Map、Set、ArrayBuffer、Date、RegExp、Array、Object及原型链属性方法执行深拷贝
|
|
2725
|
+
* @param {T} source
|
|
2726
|
+
* @param {WeakMap} map
|
|
2727
|
+
* @returns {T}
|
|
2728
|
+
*/
|
|
2729
|
+
function cloneDeep(source, map = new WeakMap()) {
|
|
2730
|
+
// 处理原始类型和 null/undefined
|
|
2731
|
+
if (source === null || typeof source !== 'object') {
|
|
2732
|
+
return source;
|
|
2733
|
+
}
|
|
2734
|
+
// 处理循环引用
|
|
2735
|
+
if (map.has(source)) {
|
|
2736
|
+
return map.get(source);
|
|
2737
|
+
}
|
|
2738
|
+
// 处理 ArrayBuffer
|
|
2739
|
+
if (source instanceof ArrayBuffer) {
|
|
2740
|
+
const copy = new ArrayBuffer(source.byteLength);
|
|
2741
|
+
new Uint8Array(copy).set(new Uint8Array(source));
|
|
2742
|
+
map.set(source, copy);
|
|
2743
|
+
return copy;
|
|
2744
|
+
}
|
|
2745
|
+
// 处理 DataView 和 TypedArray (Uint8Array 等)
|
|
2746
|
+
if (ArrayBuffer.isView(source)) {
|
|
2747
|
+
const constructor = source.constructor;
|
|
2748
|
+
const bufferCopy = cloneDeep(source.buffer, map);
|
|
2749
|
+
return new constructor(bufferCopy, source.byteOffset, source.length);
|
|
2750
|
+
}
|
|
2751
|
+
// 处理 Date 对象
|
|
2752
|
+
if (source instanceof Date) {
|
|
2753
|
+
const copy = new Date(source.getTime());
|
|
2754
|
+
map.set(source, copy);
|
|
2755
|
+
return copy;
|
|
2756
|
+
}
|
|
2757
|
+
// 处理 RegExp 对象
|
|
2758
|
+
if (source instanceof RegExp) {
|
|
2759
|
+
const copy = new RegExp(source.source, source.flags);
|
|
2760
|
+
copy.lastIndex = source.lastIndex; // 保留匹配状态
|
|
2761
|
+
map.set(source, copy);
|
|
2762
|
+
return copy;
|
|
2763
|
+
}
|
|
2764
|
+
// 处理 Map
|
|
2765
|
+
if (source instanceof Map) {
|
|
2766
|
+
const copy = new Map();
|
|
2767
|
+
map.set(source, copy);
|
|
2768
|
+
source.forEach((value, key) => {
|
|
2769
|
+
copy.set(cloneDeep(key, map), cloneDeep(value, map));
|
|
2770
|
+
});
|
|
2771
|
+
return copy;
|
|
2772
|
+
}
|
|
2773
|
+
// 处理 Set
|
|
2774
|
+
if (source instanceof Set) {
|
|
2775
|
+
const copy = new Set();
|
|
2776
|
+
map.set(source, copy);
|
|
2777
|
+
source.forEach(value => {
|
|
2778
|
+
copy.add(cloneDeep(value, map));
|
|
2779
|
+
});
|
|
2780
|
+
return copy;
|
|
2781
|
+
}
|
|
2782
|
+
// 处理数组 (包含稀疏数组)
|
|
2783
|
+
if (Array.isArray(source)) {
|
|
2784
|
+
const copy = new Array(source.length);
|
|
2785
|
+
map.set(source, copy);
|
|
2786
|
+
// 克隆所有有效索引
|
|
2787
|
+
for (let i = 0, len = source.length; i < len; i++) {
|
|
2788
|
+
if (i in source) {
|
|
2789
|
+
// 保留空位
|
|
2790
|
+
copy[i] = cloneDeep(source[i], map);
|
|
2791
|
+
}
|
|
2792
|
+
}
|
|
2793
|
+
// 克隆数组的自定义属性
|
|
2794
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
2795
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
2796
|
+
Object.defineProperty(copy, key, {
|
|
2797
|
+
...descriptors[key],
|
|
2798
|
+
value: cloneDeep(descriptors[key].value, map)
|
|
2799
|
+
});
|
|
2800
|
+
}
|
|
2801
|
+
return copy;
|
|
2802
|
+
}
|
|
2803
|
+
// 处理普通对象和类实例
|
|
2804
|
+
const copy = Object.create(Object.getPrototypeOf(source));
|
|
2805
|
+
map.set(source, copy);
|
|
2806
|
+
const descriptors = Object.getOwnPropertyDescriptors(source);
|
|
2807
|
+
for (const key of Reflect.ownKeys(descriptors)) {
|
|
2808
|
+
const descriptor = descriptors[key];
|
|
2809
|
+
if ('value' in descriptor) {
|
|
2810
|
+
// 克隆数据属性
|
|
2811
|
+
descriptor.value = cloneDeep(descriptor.value, map);
|
|
2812
|
+
}
|
|
2813
|
+
else {
|
|
2814
|
+
// 处理访问器属性 (getter/setter)
|
|
2815
|
+
if (descriptor.get) {
|
|
2816
|
+
descriptor.get = cloneDeep(descriptor.get, map);
|
|
2817
|
+
}
|
|
2818
|
+
if (descriptor.set) {
|
|
2819
|
+
descriptor.set = cloneDeep(descriptor.set, map);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
Object.defineProperty(copy, key, descriptor);
|
|
2823
|
+
}
|
|
2824
|
+
return copy;
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2827
|
+
/**
|
|
2828
|
+
* 比较两值是否相等,适用所有数据类型
|
|
2829
|
+
* @param {Comparable} a
|
|
2830
|
+
* @param {Comparable} b
|
|
2831
|
+
* @returns {boolean}
|
|
2832
|
+
*/
|
|
2833
|
+
function isEqual(a, b) {
|
|
2834
|
+
return deepEqual(a, b);
|
|
2835
|
+
}
|
|
2836
|
+
function deepEqual(a, b, compared = new WeakMap()) {
|
|
2837
|
+
// 相同值快速返回
|
|
2838
|
+
if (Object.is(a, b))
|
|
2839
|
+
return true;
|
|
2840
|
+
// 类型不同直接返回false
|
|
2841
|
+
const typeA = Object.prototype.toString.call(a);
|
|
2842
|
+
const typeB = Object.prototype.toString.call(b);
|
|
2843
|
+
if (typeA !== typeB)
|
|
2844
|
+
return false;
|
|
2845
|
+
// 只缓存对象类型
|
|
2846
|
+
if (isObject(a) && isObject(b)) {
|
|
2847
|
+
if (compared.has(a))
|
|
2848
|
+
return compared.get(a) === b;
|
|
2849
|
+
compared.set(a, b);
|
|
2850
|
+
compared.set(b, a);
|
|
2851
|
+
}
|
|
2852
|
+
// 处理特殊对象类型
|
|
2853
|
+
switch (typeA) {
|
|
2854
|
+
case '[object Date]':
|
|
2855
|
+
return a.getTime() === b.getTime();
|
|
2856
|
+
case '[object RegExp]':
|
|
2857
|
+
return a.toString() === b.toString();
|
|
2858
|
+
case '[object Map]':
|
|
2859
|
+
return compareMap(a, b, compared);
|
|
2860
|
+
case '[object Set]':
|
|
2861
|
+
return compareSet(a, b, compared);
|
|
2862
|
+
case '[object ArrayBuffer]':
|
|
2863
|
+
return compareArrayBuffer(a, b);
|
|
2864
|
+
case '[object DataView]':
|
|
2865
|
+
return compareDataView(a, b, compared);
|
|
2866
|
+
case '[object Int8Array]':
|
|
2867
|
+
case '[object Uint8Array]':
|
|
2868
|
+
case '[object Uint8ClampedArray]':
|
|
2869
|
+
case '[object Int16Array]':
|
|
2870
|
+
case '[object Uint16Array]':
|
|
2871
|
+
case '[object Int32Array]':
|
|
2872
|
+
case '[object Uint32Array]':
|
|
2873
|
+
case '[object Float32Array]':
|
|
2874
|
+
case '[object Float64Array]':
|
|
2875
|
+
return compareTypedArray(a, b, compared);
|
|
2876
|
+
case '[object Object]':
|
|
2877
|
+
return compareObjects(a, b, compared);
|
|
2878
|
+
case '[object Array]':
|
|
2879
|
+
return compareArrays(a, b, compared);
|
|
2880
|
+
}
|
|
2881
|
+
return false;
|
|
2882
|
+
}
|
|
2883
|
+
// 辅助比较函数
|
|
2884
|
+
function compareMap(a, b, compared) {
|
|
2885
|
+
if (a.size !== b.size)
|
|
2886
|
+
return false;
|
|
2887
|
+
for (const [key, value] of a) {
|
|
2888
|
+
if (!b.has(key) || !deepEqual(value, b.get(key), compared))
|
|
2889
|
+
return false;
|
|
2890
|
+
}
|
|
2891
|
+
return true;
|
|
2892
|
+
}
|
|
2893
|
+
function compareSet(a, b, compared) {
|
|
2894
|
+
if (a.size !== b.size)
|
|
2895
|
+
return false;
|
|
2896
|
+
for (const value of a) {
|
|
2897
|
+
let found = false;
|
|
2898
|
+
for (const bValue of b) {
|
|
2899
|
+
if (deepEqual(value, bValue, compared)) {
|
|
2900
|
+
found = true;
|
|
2901
|
+
break;
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
if (!found)
|
|
2905
|
+
return false;
|
|
2906
|
+
}
|
|
2907
|
+
return true;
|
|
2908
|
+
}
|
|
2909
|
+
function compareArrayBuffer(a, b) {
|
|
2910
|
+
if (a.byteLength !== b.byteLength)
|
|
2911
|
+
return false;
|
|
2912
|
+
return new DataView(a).getInt32(0) === new DataView(b).getInt32(0);
|
|
2913
|
+
}
|
|
2914
|
+
function compareDataView(a, b, compared) {
|
|
2915
|
+
return a.byteLength === b.byteLength && deepEqual(new Uint8Array(a.buffer), new Uint8Array(b.buffer), compared);
|
|
2916
|
+
}
|
|
2917
|
+
function compareTypedArray(a, b, compared) {
|
|
2918
|
+
return a.byteLength === b.byteLength && deepEqual(Array.from(a), Array.from(b), compared);
|
|
2919
|
+
}
|
|
2920
|
+
function compareObjects(a, b, compared) {
|
|
2921
|
+
const keysA = Reflect.ownKeys(a);
|
|
2922
|
+
const keysB = Reflect.ownKeys(b);
|
|
2923
|
+
if (keysA.length !== keysB.length)
|
|
2924
|
+
return false;
|
|
2925
|
+
for (const key of keysA) {
|
|
2926
|
+
if (!keysB.includes(key))
|
|
2927
|
+
return false;
|
|
2928
|
+
if (!deepEqual(a[key], b[key], compared))
|
|
2929
|
+
return false;
|
|
2930
|
+
}
|
|
2931
|
+
// 原型链比较
|
|
2932
|
+
return Object.getPrototypeOf(a) === Object.getPrototypeOf(b);
|
|
2933
|
+
}
|
|
2934
|
+
function compareArrays(a, b, compared) {
|
|
2935
|
+
// 增加有效索引检查
|
|
2936
|
+
const keysA = Object.keys(a).map(Number);
|
|
2937
|
+
const keysB = Object.keys(b).map(Number);
|
|
2938
|
+
if (keysA.length !== keysB.length)
|
|
2939
|
+
return false;
|
|
2940
|
+
// 递归比较每个元素
|
|
2941
|
+
for (let i = 0, len = a.length; i < len; i++) {
|
|
2942
|
+
if (!deepEqual(a[i], b[i], compared))
|
|
2943
|
+
return false;
|
|
2944
|
+
}
|
|
2945
|
+
// 比较数组对象的其他属性
|
|
2946
|
+
return compareObjects(a, b, compared);
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2954
2949
|
exports.EMAIL_REGEX = EMAIL_REGEX;
|
|
2955
2950
|
exports.HEX_POOL = HEX_POOL;
|
|
2956
2951
|
exports.HTTP_URL_REGEX = HTTP_URL_REGEX;
|