@codady/utils 0.0.12 → 0.0.14
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/CHANGELOG.md +36 -0
- package/dist/utils.cjs.js +60 -10
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +60 -10
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +60 -10
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/modules.js +3 -1
- package/modules.ts +3 -1
- package/package.json +1 -1
- package/src/copyObjectWithSymbol.js +26 -0
- package/src/copyObjectWithSymbol.ts +28 -0
- package/src/deepClone.js +14 -2
- package/src/deepClone.ts +36 -14
- package/src/getDataType - /345/211/257/346/234/254.js" +38 -0
- package/src/isEmpty - /345/211/257/346/234/254.js" +45 -0
- package/src/isEmpty.js +45 -0
- package/src/isEmpty.ts +44 -0
- package/src/shallowCopy.js +40 -8
- package/src/shallowCopy.ts +47 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,42 @@
|
|
|
3
3
|
All changes to Utils including new features, updates, and removals are documented here.
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
## [v0.0.14] - 2025-12-26
|
|
7
|
+
|
|
8
|
+
### Distribution Files
|
|
9
|
+
* **JS**: https://unpkg.com/@codady/utils@0.0.14/dist/js/utils.js
|
|
10
|
+
* **Zip**:https://unpkg.com/@codady/utils@0.0.14/dist.zip
|
|
11
|
+
|
|
12
|
+
### Changes
|
|
13
|
+
|
|
14
|
+
#### Fixed
|
|
15
|
+
* Null
|
|
16
|
+
|
|
17
|
+
#### Added
|
|
18
|
+
* The `onBeforeClone` and `onAfterClone` callbacks of the `deepClone` function now include a new `parent` property, which can temporarily store the parent object being cloned. deepClone函数的onBeforeClone和onAfterClone新增属性parent,可临时存储被拷贝的父对象。
|
|
19
|
+
|
|
20
|
+
#### Removed
|
|
21
|
+
* Null
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
## [v0.0.13] - 2025-12-25
|
|
25
|
+
|
|
26
|
+
### Distribution Files
|
|
27
|
+
* **JS**: https://unpkg.com/@codady/utils@0.0.13/dist/js/utils.js
|
|
28
|
+
* **Zip**:https://unpkg.com/@codady/utils@0.0.13/dist.zip
|
|
29
|
+
|
|
30
|
+
### Changes
|
|
31
|
+
|
|
32
|
+
#### Fixed
|
|
33
|
+
* Modify the `shallowCopy` function to add support for data types such as Date, Regex, Error, Buffer, ArrayBuffer, WeakSet, and WeakMap.修改`shallowCopy`函数,增加对Date、Regex、Error、Buffer、ArrayBuffer、WeakSet、WeakMap数据类型的支持。
|
|
34
|
+
|
|
35
|
+
#### Added
|
|
36
|
+
* Added the following functions: `copyObjectWithSymbol`.新增`copyObjectWithSymbol`函数。
|
|
37
|
+
|
|
38
|
+
#### Removed
|
|
39
|
+
* Null
|
|
40
|
+
|
|
41
|
+
|
|
6
42
|
## [v0.0.12] - 2025-12-25
|
|
7
43
|
|
|
8
44
|
### Distribution Files
|
package/dist/utils.cjs.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* @since Last modified: 2025-12-
|
|
3
|
+
* @since Last modified: 2025-12-26 9:45:49
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.14
|
|
6
6
|
* @author AXUI development team <3217728223@qq.com>
|
|
7
7
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
8
8
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -69,18 +69,26 @@ const deepClone = (data, options = {}) => {
|
|
|
69
69
|
input: data,
|
|
70
70
|
type: dataType,
|
|
71
71
|
cloned: result !== data,
|
|
72
|
+
parent: opts.parent
|
|
72
73
|
});
|
|
73
74
|
return result;
|
|
74
75
|
}
|
|
75
76
|
// If interceptor returns null/undefined, continue with normal cloning process
|
|
76
77
|
}
|
|
77
78
|
// Callback before cloning
|
|
78
|
-
opts.onBeforeClone?.(
|
|
79
|
+
opts.onBeforeClone?.({
|
|
80
|
+
input: data,
|
|
81
|
+
type: dataType,
|
|
82
|
+
parent: opts.parent
|
|
83
|
+
});
|
|
79
84
|
let newData, cloned = true;
|
|
80
85
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
81
86
|
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
87
|
+
//存储parent对象,在下一次深复制时使用
|
|
88
|
+
opts.parent = data;
|
|
82
89
|
// Clone regular properties
|
|
83
90
|
for (const key in data) {
|
|
91
|
+
//临时保存父对象
|
|
84
92
|
newObj[key] = deepClone(data[key], opts);
|
|
85
93
|
}
|
|
86
94
|
// Clone Symbol properties
|
|
@@ -92,10 +100,12 @@ const deepClone = (data, options = {}) => {
|
|
|
92
100
|
newData = newObj;
|
|
93
101
|
}
|
|
94
102
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
103
|
+
opts.parent = data;
|
|
95
104
|
newData = data.map(item => deepClone(item, opts));
|
|
96
105
|
}
|
|
97
106
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
98
107
|
const newMap = new Map();
|
|
108
|
+
opts.parent = data;
|
|
99
109
|
for (const [key, value] of data) {
|
|
100
110
|
// Both Map keys and values need deep cloning
|
|
101
111
|
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
@@ -104,6 +114,7 @@ const deepClone = (data, options = {}) => {
|
|
|
104
114
|
}
|
|
105
115
|
else if (dataType === 'Set' && opts.cloneSet) {
|
|
106
116
|
const newSet = new Set();
|
|
117
|
+
opts.parent = data;
|
|
107
118
|
for (const value of data) {
|
|
108
119
|
// Set values need deep cloning
|
|
109
120
|
newSet.add(deepClone(value, opts));
|
|
@@ -133,6 +144,7 @@ const deepClone = (data, options = {}) => {
|
|
|
133
144
|
input: data,
|
|
134
145
|
type: dataType,
|
|
135
146
|
cloned,
|
|
147
|
+
parent: opts.parent
|
|
136
148
|
});
|
|
137
149
|
return newData;
|
|
138
150
|
};
|
|
@@ -422,7 +434,20 @@ const wrapMapMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = ()
|
|
|
422
434
|
return methods;
|
|
423
435
|
};
|
|
424
436
|
|
|
425
|
-
const
|
|
437
|
+
const copyObjectWithSymbol = (data) => {
|
|
438
|
+
if (!data || typeof data !== 'object') {
|
|
439
|
+
return data;
|
|
440
|
+
}
|
|
441
|
+
// Ensure the object type includes string and symbol keys
|
|
442
|
+
const obj = data, symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
|
|
443
|
+
acc[sym] = obj[sym];
|
|
444
|
+
return acc;
|
|
445
|
+
}, {});
|
|
446
|
+
// Shallow copy the object and include the Symbol properties
|
|
447
|
+
return { ...obj, ...symbolProperties };
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
const shallowCopy = (data, options = {}) => {
|
|
426
451
|
const dataType = getDataType(data);
|
|
427
452
|
// Check if data is a Set
|
|
428
453
|
if (dataType === 'Set') {
|
|
@@ -441,13 +466,37 @@ const shallowCopy = (data) => {
|
|
|
441
466
|
}
|
|
442
467
|
// Check if data is a Plain Object (including Symbol keys)
|
|
443
468
|
if (dataType === 'object') {
|
|
444
|
-
|
|
445
|
-
const symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
|
|
446
|
-
acc[sym] = obj[sym];
|
|
447
|
-
return acc;
|
|
448
|
-
}, {});
|
|
469
|
+
// Ensure the object type includes string and symbol keys
|
|
449
470
|
// Shallow copy the object and include the Symbol properties
|
|
450
|
-
return
|
|
471
|
+
return copyObjectWithSymbol(data);
|
|
472
|
+
}
|
|
473
|
+
// Check if data is a Date
|
|
474
|
+
if (dataType === 'Date') {
|
|
475
|
+
return new Date(data.getTime());
|
|
476
|
+
}
|
|
477
|
+
// Check if data is a RegExp
|
|
478
|
+
if (dataType === 'RegExp') {
|
|
479
|
+
return new RegExp(data.source, data.flags);
|
|
480
|
+
}
|
|
481
|
+
// Check if data is a Buffer (for Node.js)
|
|
482
|
+
if (dataType === 'Buffer') {
|
|
483
|
+
return Buffer.from(data);
|
|
484
|
+
}
|
|
485
|
+
// Check if data is an ArrayBuffer or TypedArray
|
|
486
|
+
if (dataType === 'ArrayBuffer' || ArrayBuffer.isView(data)) {
|
|
487
|
+
return data.slice(0);
|
|
488
|
+
}
|
|
489
|
+
// Check if data is a WeakSet
|
|
490
|
+
if (dataType === 'WeakSet') {
|
|
491
|
+
return new WeakSet([...data]);
|
|
492
|
+
}
|
|
493
|
+
// Check if data is a WeakMap
|
|
494
|
+
if (dataType === 'WeakMap') {
|
|
495
|
+
return new WeakMap([...data]);
|
|
496
|
+
}
|
|
497
|
+
// Check if data is an Error
|
|
498
|
+
if (dataType === 'Error') {
|
|
499
|
+
return new Error(data.message);
|
|
451
500
|
}
|
|
452
501
|
// For other types (such as numbers, strings, booleans, etc.), return the original value
|
|
453
502
|
return data;
|
|
@@ -708,6 +757,7 @@ const utils = {
|
|
|
708
757
|
getUniqueId,
|
|
709
758
|
deepMerge,
|
|
710
759
|
shallowCopy,
|
|
760
|
+
copyObjectWithSymbol,
|
|
711
761
|
};
|
|
712
762
|
|
|
713
763
|
module.exports = utils;
|
package/dist/utils.cjs.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @since Last modified: 2025-12-
|
|
2
|
+
* @since Last modified: 2025-12-26 9:45:49
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.14
|
|
5
5
|
* @author AXUI development team <3217728223@qq.com>
|
|
6
6
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
7
7
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'ax,' 'axui,' 'AX,' and 'AXUI' within the software.
|
|
13
13
|
* @license MIT license
|
|
14
14
|
*/
|
|
15
|
-
"use strict";const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),o=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(o.interceptor&&"function"==typeof o.interceptor){let t=o.interceptor(e,r);if(t)return o.onAfterClone?.({output:t,input:e,type:r,cloned:t!==e}),t}o.onBeforeClone?.(e,r);let a,n=!0;if("Object"===r&&o.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);for(const r in e)t[r]=deepClone(e[r],o);if(r.length>0)for(const a of r)t[a]=deepClone(e[a],o);a=t}else if("Array"===r&&o.cloneArray)a=e.map(e=>deepClone(e,o));else if("Map"===r&&o.cloneMap){const t=new Map;for(const[r,a]of e)t.set(deepClone(r,o),deepClone(a,o));a=t}else if("Set"===r&&o.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,o));a=t}else if("Date"===r&&o.cloneDate)a=new Date(e.getTime());else if("RegExp"===r&&o.cloneRegex){const t=e;a=new RegExp(t.source,t.flags)}else a=e,n=!1;return o.onAfterClone?.({output:a,input:e,type:r,cloned:n}),a},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const r in e)t[r]=deepCloneToJSON(e[r]);for(const e in t)void 0===t[e]&&Reflect.deleteProperty(t,e);return t}if("Array"===t){return e.map((e,t)=>deepCloneToJSON(e)).filter(e=>void 0!==e)}return["Number","String","Boolean","Null"].includes(t)?e:void 0},arrayMutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],wrapArrayMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:o,props:a={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");o&&!o?.length||(o=arrayMutableMethods);const n={};for(let s of o)n[s]=function(...o){const n={},l=e.length;switch(s){case"push":case"unshift":n.addedItems=[...o];break;case"pop":n.poppedItem=e[l-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=o,a=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===r?l-a:r;n.deletedItems=e.slice(a,a+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const i=o[1]||0,
|
|
15
|
+
"use strict";const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),o=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(o.interceptor&&"function"==typeof o.interceptor){let t=o.interceptor(e,r);if(t)return o.onAfterClone?.({output:t,input:e,type:r,cloned:t!==e,parent:o.parent}),t}o.onBeforeClone?.({input:e,type:r,parent:o.parent});let a,n=!0;if("Object"===r&&o.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);o.parent=e;for(const r in e)t[r]=deepClone(e[r],o);if(r.length>0)for(const a of r)t[a]=deepClone(e[a],o);a=t}else if("Array"===r&&o.cloneArray)o.parent=e,a=e.map(e=>deepClone(e,o));else if("Map"===r&&o.cloneMap){const t=new Map;o.parent=e;for(const[r,a]of e)t.set(deepClone(r,o),deepClone(a,o));a=t}else if("Set"===r&&o.cloneSet){const t=new Set;o.parent=e;for(const r of e)t.add(deepClone(r,o));a=t}else if("Date"===r&&o.cloneDate)a=new Date(e.getTime());else if("RegExp"===r&&o.cloneRegex){const t=e;a=new RegExp(t.source,t.flags)}else a=e,n=!1;return o.onAfterClone?.({output:a,input:e,type:r,cloned:n,parent:o.parent}),a},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const r in e)t[r]=deepCloneToJSON(e[r]);for(const e in t)void 0===t[e]&&Reflect.deleteProperty(t,e);return t}if("Array"===t){return e.map((e,t)=>deepCloneToJSON(e)).filter(e=>void 0!==e)}return["Number","String","Boolean","Null"].includes(t)?e:void 0},arrayMutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],wrapArrayMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:o,props:a={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");o&&!o?.length||(o=arrayMutableMethods);const n={};for(let s of o)n[s]=function(...o){const n={},l=e.length;switch(s){case"push":case"unshift":n.addedItems=[...o];break;case"pop":n.poppedItem=e[l-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=o,a=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===r?l-a:r;n.deletedItems=e.slice(a,a+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const i=o[1]||0,p=void 0===o[2]?l:o[2];n.oldItems=e.slice(i,p),n.start=i,n.end=p}t?.(n);const i=Array.prototype[s].apply(e,o),p={value:i,key:s,args:o,context:n,target:e,...a};return r?.(p),i};return n},requireTypes=(e,t,r)=>{let o=Array.isArray(t)?t:[t],a=getDataType(e),n=a.toLowerCase(),s=o.map(e=>e.toLowerCase()),l=n.includes("html")?"element":n;if(r)try{if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`)}catch(e){r(e,a)}else if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`);return a},getUniqueId=(e={})=>{const t=e.prefix,r=e.suffix,o=e.base10,a=e.base36;return`${t?t+"-":""}${Date.now()}${a?"-"+Math.random().toString(36).substring(2,11):""}${o?"-"+Math.floor(1e4*Math.random()).toString().padStart(4,"0"):""}${r?"-"+r:""}`},setMutableMethods=["add","delete","clear"],mapMutableMethods=["set","delete","clear"],wrapSetMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:o=setMutableMethods,props:a={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const n={},createWrappedMethod=o=>function(...n){const s={};switch(o){case"add":{const[t]=n;s.addedItem=t,s.existed=e.has(t);break}case"delete":{const[t]=n;s.existed=e.has(t),s.deletedItem=s.existed?t:void 0;break}case"clear":s.clearedItems=Array.from(e),s.previousSize=e.size}t(s);const l=e[o].apply(e,n),i={method:o,result:l,args:n,context:s,target:e,...a};return r(i),l};for(const e of o)setMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},wrapMapMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:o=mapMutableMethods,props:a={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const n={},createWrappedMethod=o=>function(...n){const s={};switch(o){case"set":{const[t,r]=n;s.key=t,s.newValue=r,s.existed=e.has(t),s.oldValue=s.existed?e.get(t):void 0;break}case"delete":{const[t]=n;s.key=t,s.existed=e.has(t),s.value=s.existed?e.get(t):void 0;break}case"clear":s.clearedItems=Array.from(e.entries()),s.previousSize=e.size}t(s);const l=e[o].apply(e,n),i={method:o,result:l,args:n,context:s,target:e,...a};return r(i),l};for(const e of o)mapMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},copyObjectWithSymbol=e=>{if(!e||"object"!=typeof e)return e;const t=e,r=Object.getOwnPropertySymbols(t).reduce((e,r)=>(e[r]=t[r],e),{});return{...t,...r}},shallowCopy=(e,t={})=>{const r=getDataType(e);return"Set"===r?new Set([...e]):"Map"===r?new Map([...e]):Array.isArray(e)?[...e]:"object"===r?copyObjectWithSymbol(e):"Date"===r?new Date(e.getTime()):"RegExp"===r?new RegExp(e.source,e.flags):"Buffer"===r?Buffer.from(e):"ArrayBuffer"===r||ArrayBuffer.isView(e)?e.slice(0):"WeakSet"===r?new WeakSet([...e]):"WeakMap"===r?new WeakMap([...e]):"Error"===r?new Error(e.message):e},deepMerge=(e,t,r={})=>{const o=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0,useSymbol:!0,deepClone:{},onBeforeMerge:void 0,onAfterMerge:void 0},r),deepMergeHelper=(e,t,r)=>{let o,a,n=getDataType(e),s=getDataType(t),l=!0;return"Object"===n&&"Object"===s?(a=deepMergeObjects(e,t,r),o="Object"):"Array"===n&&"Array"===s?(a=deepMergeArrays(e,t,r),o="Array"):"Set"===n&&"Set"===s?(a=deepMergeSets(e,t,r),o="Set"):"Map"===n&&"Map"===s?(a=deepMergeMaps(e,t,r),o="Map"):(l=!1,a=e),{result:a,flag:l,type:o}},mergeEnableObject=(e,t)=>e?.hasOwnProperty("enable")&&"boolean"==typeof t?(e.enable=t,e):t?.hasOwnProperty("enable")&&"boolean"==typeof e?Object.assign({enable:e},t):t,deepMergeObjects=(e,t,r={})=>{let o=getDataType(e),a=getDataType(t);if("Object"!==o||"Object"!==a)return e;r?.onBeforeMerge?.(e,t);const n=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r);let s={};s=n.targetClone?shallowCopy(e):e;for(let e in t)if(t.hasOwnProperty(e)&&s.hasOwnProperty(e)){let o=deepMergeHelper(s[e],t[e],r);o.flag?o.type?"Object"===o.type&&(s[e]=o.result):s[e]=t[e]:n.useEnable?s[e]=mergeEnableObject(s[e],t[e]):s[e]=t[e]}else t.hasOwnProperty(e)&&!s.hasOwnProperty(e)&&n.inheritMissing&&(s[e]=t[e]);if(n.useSymbol){let e=Object.getOwnPropertySymbols(t);if(e.length)for(let r of e)s[r]=t[r]}return n?.onAfterMerge?.(s,e,t),s},deepMergeArrays=(e,t,r={})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;r?.onBeforeMerge?.(e,t);const o=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1},r),a=o.targetClone?[...e]:e;if("replace"===o.dataMode)for(let e=0;e<t.length&&(o.inheritMissing||!(e>=a.length));e++){deepMergeHelper(a[e],t[e],o).flag||(a[e]=t[e])}else"concat"===o.dataMode||(a.length=0),a.push(...t);return r?.onAfterMerge?.(a,e,t),a},deepMergeMaps=(e,t,r={})=>{if(!(e instanceof Map&&t instanceof Map))return e;r?.onBeforeMerge?.(e,t);const o=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r),a=o.targetClone?new Map([...e]):e;for(const[e,n]of t.entries())if(a.has(e)){const t=a.get(e),r=n,s=deepMergeHelper(t,r,o);s.flag?"Object"===s.type&&a.set(e,s.result):a.set(e,r)}else r.inheritMissing&&a.set(e,n);return r?.onAfterMerge?.(a,e,t),a},deepMergeSets=(e,t,r={})=>{if(!(e instanceof Set&&t instanceof Set))return e;r?.onBeforeMerge?.(e,t);const o=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0},r),a=o.targetClone?new Set(...e):e;if("replace"===o.dataMode){const e=[...a],r=[...t],n=deepMergeHelper(e,r,o);a.clear();for(let e of n.result)a.add(e)}else if("concat"===o.dataMode)for(let e of t)a.add(e);else{a.clear();for(let e of t)a.add(e)}return r?.onAfterMerge?.(a,e,t),a};return deepMergeHelper(e,t,o).result},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:wrapArrayMethods,arrayMutableMethods:arrayMutableMethods,setMutableMethods:setMutableMethods,mapMutableMethods:mapMutableMethods,wrapSetMethods:wrapSetMethods,wrapMapMethods:wrapMapMethods,getUniqueId:getUniqueId,deepMerge:deepMerge,shallowCopy:shallowCopy,copyObjectWithSymbol:copyObjectWithSymbol};module.exports=utils;
|
package/dist/utils.esm.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* @since Last modified: 2025-12-
|
|
3
|
+
* @since Last modified: 2025-12-26 9:45:49
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.14
|
|
6
6
|
* @author AXUI development team <3217728223@qq.com>
|
|
7
7
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
8
8
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -67,18 +67,26 @@ const deepClone = (data, options = {}) => {
|
|
|
67
67
|
input: data,
|
|
68
68
|
type: dataType,
|
|
69
69
|
cloned: result !== data,
|
|
70
|
+
parent: opts.parent
|
|
70
71
|
});
|
|
71
72
|
return result;
|
|
72
73
|
}
|
|
73
74
|
// If interceptor returns null/undefined, continue with normal cloning process
|
|
74
75
|
}
|
|
75
76
|
// Callback before cloning
|
|
76
|
-
opts.onBeforeClone?.(
|
|
77
|
+
opts.onBeforeClone?.({
|
|
78
|
+
input: data,
|
|
79
|
+
type: dataType,
|
|
80
|
+
parent: opts.parent
|
|
81
|
+
});
|
|
77
82
|
let newData, cloned = true;
|
|
78
83
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
79
84
|
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
85
|
+
//存储parent对象,在下一次深复制时使用
|
|
86
|
+
opts.parent = data;
|
|
80
87
|
// Clone regular properties
|
|
81
88
|
for (const key in data) {
|
|
89
|
+
//临时保存父对象
|
|
82
90
|
newObj[key] = deepClone(data[key], opts);
|
|
83
91
|
}
|
|
84
92
|
// Clone Symbol properties
|
|
@@ -90,10 +98,12 @@ const deepClone = (data, options = {}) => {
|
|
|
90
98
|
newData = newObj;
|
|
91
99
|
}
|
|
92
100
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
101
|
+
opts.parent = data;
|
|
93
102
|
newData = data.map(item => deepClone(item, opts));
|
|
94
103
|
}
|
|
95
104
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
96
105
|
const newMap = new Map();
|
|
106
|
+
opts.parent = data;
|
|
97
107
|
for (const [key, value] of data) {
|
|
98
108
|
// Both Map keys and values need deep cloning
|
|
99
109
|
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
@@ -102,6 +112,7 @@ const deepClone = (data, options = {}) => {
|
|
|
102
112
|
}
|
|
103
113
|
else if (dataType === 'Set' && opts.cloneSet) {
|
|
104
114
|
const newSet = new Set();
|
|
115
|
+
opts.parent = data;
|
|
105
116
|
for (const value of data) {
|
|
106
117
|
// Set values need deep cloning
|
|
107
118
|
newSet.add(deepClone(value, opts));
|
|
@@ -131,6 +142,7 @@ const deepClone = (data, options = {}) => {
|
|
|
131
142
|
input: data,
|
|
132
143
|
type: dataType,
|
|
133
144
|
cloned,
|
|
145
|
+
parent: opts.parent
|
|
134
146
|
});
|
|
135
147
|
return newData;
|
|
136
148
|
};
|
|
@@ -420,7 +432,20 @@ const wrapMapMethods = ({ target, onBeforeMutate = () => { }, onAfterMutate = ()
|
|
|
420
432
|
return methods;
|
|
421
433
|
};
|
|
422
434
|
|
|
423
|
-
const
|
|
435
|
+
const copyObjectWithSymbol = (data) => {
|
|
436
|
+
if (!data || typeof data !== 'object') {
|
|
437
|
+
return data;
|
|
438
|
+
}
|
|
439
|
+
// Ensure the object type includes string and symbol keys
|
|
440
|
+
const obj = data, symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
|
|
441
|
+
acc[sym] = obj[sym];
|
|
442
|
+
return acc;
|
|
443
|
+
}, {});
|
|
444
|
+
// Shallow copy the object and include the Symbol properties
|
|
445
|
+
return { ...obj, ...symbolProperties };
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const shallowCopy = (data, options = {}) => {
|
|
424
449
|
const dataType = getDataType(data);
|
|
425
450
|
// Check if data is a Set
|
|
426
451
|
if (dataType === 'Set') {
|
|
@@ -439,13 +464,37 @@ const shallowCopy = (data) => {
|
|
|
439
464
|
}
|
|
440
465
|
// Check if data is a Plain Object (including Symbol keys)
|
|
441
466
|
if (dataType === 'object') {
|
|
442
|
-
|
|
443
|
-
const symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
|
|
444
|
-
acc[sym] = obj[sym];
|
|
445
|
-
return acc;
|
|
446
|
-
}, {});
|
|
467
|
+
// Ensure the object type includes string and symbol keys
|
|
447
468
|
// Shallow copy the object and include the Symbol properties
|
|
448
|
-
return
|
|
469
|
+
return copyObjectWithSymbol(data);
|
|
470
|
+
}
|
|
471
|
+
// Check if data is a Date
|
|
472
|
+
if (dataType === 'Date') {
|
|
473
|
+
return new Date(data.getTime());
|
|
474
|
+
}
|
|
475
|
+
// Check if data is a RegExp
|
|
476
|
+
if (dataType === 'RegExp') {
|
|
477
|
+
return new RegExp(data.source, data.flags);
|
|
478
|
+
}
|
|
479
|
+
// Check if data is a Buffer (for Node.js)
|
|
480
|
+
if (dataType === 'Buffer') {
|
|
481
|
+
return Buffer.from(data);
|
|
482
|
+
}
|
|
483
|
+
// Check if data is an ArrayBuffer or TypedArray
|
|
484
|
+
if (dataType === 'ArrayBuffer' || ArrayBuffer.isView(data)) {
|
|
485
|
+
return data.slice(0);
|
|
486
|
+
}
|
|
487
|
+
// Check if data is a WeakSet
|
|
488
|
+
if (dataType === 'WeakSet') {
|
|
489
|
+
return new WeakSet([...data]);
|
|
490
|
+
}
|
|
491
|
+
// Check if data is a WeakMap
|
|
492
|
+
if (dataType === 'WeakMap') {
|
|
493
|
+
return new WeakMap([...data]);
|
|
494
|
+
}
|
|
495
|
+
// Check if data is an Error
|
|
496
|
+
if (dataType === 'Error') {
|
|
497
|
+
return new Error(data.message);
|
|
449
498
|
}
|
|
450
499
|
// For other types (such as numbers, strings, booleans, etc.), return the original value
|
|
451
500
|
return data;
|
|
@@ -706,6 +755,7 @@ const utils = {
|
|
|
706
755
|
getUniqueId,
|
|
707
756
|
deepMerge,
|
|
708
757
|
shallowCopy,
|
|
758
|
+
copyObjectWithSymbol,
|
|
709
759
|
};
|
|
710
760
|
|
|
711
761
|
export { utils as default };
|
package/dist/utils.esm.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @since Last modified: 2025-12-
|
|
2
|
+
* @since Last modified: 2025-12-26 9:45:49
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.14
|
|
5
5
|
* @author AXUI development team <3217728223@qq.com>
|
|
6
6
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
7
7
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'ax,' 'axui,' 'AX,' and 'AXUI' within the software.
|
|
13
13
|
* @license MIT license
|
|
14
14
|
*/
|
|
15
|
-
const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),
|
|
15
|
+
const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),a=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(a.interceptor&&"function"==typeof a.interceptor){let t=a.interceptor(e,r);if(t)return a.onAfterClone?.({output:t,input:e,type:r,cloned:t!==e,parent:a.parent}),t}a.onBeforeClone?.({input:e,type:r,parent:a.parent});let o,n=!0;if("Object"===r&&a.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);a.parent=e;for(const r in e)t[r]=deepClone(e[r],a);if(r.length>0)for(const o of r)t[o]=deepClone(e[o],a);o=t}else if("Array"===r&&a.cloneArray)a.parent=e,o=e.map(e=>deepClone(e,a));else if("Map"===r&&a.cloneMap){const t=new Map;a.parent=e;for(const[r,o]of e)t.set(deepClone(r,a),deepClone(o,a));o=t}else if("Set"===r&&a.cloneSet){const t=new Set;a.parent=e;for(const r of e)t.add(deepClone(r,a));o=t}else if("Date"===r&&a.cloneDate)o=new Date(e.getTime());else if("RegExp"===r&&a.cloneRegex){const t=e;o=new RegExp(t.source,t.flags)}else o=e,n=!1;return a.onAfterClone?.({output:o,input:e,type:r,cloned:n,parent:a.parent}),o},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const r in e)t[r]=deepCloneToJSON(e[r]);for(const e in t)void 0===t[e]&&Reflect.deleteProperty(t,e);return t}if("Array"===t){return e.map((e,t)=>deepCloneToJSON(e)).filter(e=>void 0!==e)}return["Number","String","Boolean","Null"].includes(t)?e:void 0},arrayMutableMethods=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],wrapArrayMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a,props:o={}})=>{if(!Array.isArray(e))throw new TypeError("The 'target' parameter must be an array.");a&&!a?.length||(a=arrayMutableMethods);const n={};for(let s of a)n[s]=function(...a){const n={},l=e.length;switch(s){case"push":case"unshift":n.addedItems=[...a];break;case"pop":n.poppedItem=e[l-1];break;case"shift":n.shiftedItem=e[0];break;case"splice":const[t,r]=a,o=t<0?Math.max(l+t,0):Math.min(t,l),s=void 0===r?l-o:r;n.deletedItems=e.slice(o,o+s);break;case"sort":case"reverse":n.oldSnapshot=[...e];break;case"fill":case"copyWithin":const i=a[1]||0,p=void 0===a[2]?l:a[2];n.oldItems=e.slice(i,p),n.start=i,n.end=p}t?.(n);const i=Array.prototype[s].apply(e,a),p={value:i,key:s,args:a,context:n,target:e,...o};return r?.(p),i};return n},requireTypes=(e,t,r)=>{let a=Array.isArray(t)?t:[t],o=getDataType(e),n=o.toLowerCase(),s=a.map(e=>e.toLowerCase()),l=n.includes("html")?"element":n;if(r)try{if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`)}catch(e){r(e,o)}else if(!s.includes(l))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${l}`);return o},getUniqueId=(e={})=>{const t=e.prefix,r=e.suffix,a=e.base10,o=e.base36;return`${t?t+"-":""}${Date.now()}${o?"-"+Math.random().toString(36).substring(2,11):""}${a?"-"+Math.floor(1e4*Math.random()).toString().padStart(4,"0"):""}${r?"-"+r:""}`},setMutableMethods=["add","delete","clear"],mapMutableMethods=["set","delete","clear"],wrapSetMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a=setMutableMethods,props:o={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const n={},createWrappedMethod=a=>function(...n){const s={};switch(a){case"add":{const[t]=n;s.addedItem=t,s.existed=e.has(t);break}case"delete":{const[t]=n;s.existed=e.has(t),s.deletedItem=s.existed?t:void 0;break}case"clear":s.clearedItems=Array.from(e),s.previousSize=e.size}t(s);const l=e[a].apply(e,n),i={method:a,result:l,args:n,context:s,target:e,...o};return r(i),l};for(const e of a)setMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},wrapMapMethods=({target:e,onBeforeMutate:t=()=>{},onAfterMutate:r=()=>{},allowList:a=mapMutableMethods,props:o={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const n={},createWrappedMethod=a=>function(...n){const s={};switch(a){case"set":{const[t,r]=n;s.key=t,s.newValue=r,s.existed=e.has(t),s.oldValue=s.existed?e.get(t):void 0;break}case"delete":{const[t]=n;s.key=t,s.existed=e.has(t),s.value=s.existed?e.get(t):void 0;break}case"clear":s.clearedItems=Array.from(e.entries()),s.previousSize=e.size}t(s);const l=e[a].apply(e,n),i={method:a,result:l,args:n,context:s,target:e,...o};return r(i),l};for(const e of a)mapMutableMethods.includes(e)&&(n[e]=createWrappedMethod(e));return Object.defineProperty(n,"target",{get:()=>e,enumerable:!1,configurable:!1}),n},copyObjectWithSymbol=e=>{if(!e||"object"!=typeof e)return e;const t=e,r=Object.getOwnPropertySymbols(t).reduce((e,r)=>(e[r]=t[r],e),{});return{...t,...r}},shallowCopy=(e,t={})=>{const r=getDataType(e);return"Set"===r?new Set([...e]):"Map"===r?new Map([...e]):Array.isArray(e)?[...e]:"object"===r?copyObjectWithSymbol(e):"Date"===r?new Date(e.getTime()):"RegExp"===r?new RegExp(e.source,e.flags):"Buffer"===r?Buffer.from(e):"ArrayBuffer"===r||ArrayBuffer.isView(e)?e.slice(0):"WeakSet"===r?new WeakSet([...e]):"WeakMap"===r?new WeakMap([...e]):"Error"===r?new Error(e.message):e},deepMerge=(e,t,r={})=>{const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0,useSymbol:!0,deepClone:{},onBeforeMerge:void 0,onAfterMerge:void 0},r),deepMergeHelper=(e,t,r)=>{let a,o,n=getDataType(e),s=getDataType(t),l=!0;return"Object"===n&&"Object"===s?(o=deepMergeObjects(e,t,r),a="Object"):"Array"===n&&"Array"===s?(o=deepMergeArrays(e,t,r),a="Array"):"Set"===n&&"Set"===s?(o=deepMergeSets(e,t,r),a="Set"):"Map"===n&&"Map"===s?(o=deepMergeMaps(e,t,r),a="Map"):(l=!1,o=e),{result:o,flag:l,type:a}},mergeEnableObject=(e,t)=>e?.hasOwnProperty("enable")&&"boolean"==typeof t?(e.enable=t,e):t?.hasOwnProperty("enable")&&"boolean"==typeof e?Object.assign({enable:e},t):t,deepMergeObjects=(e,t,r={})=>{let a=getDataType(e),o=getDataType(t);if("Object"!==a||"Object"!==o)return e;r?.onBeforeMerge?.(e,t);const n=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r);let s={};s=n.targetClone?shallowCopy(e):e;for(let e in t)if(t.hasOwnProperty(e)&&s.hasOwnProperty(e)){let a=deepMergeHelper(s[e],t[e],r);a.flag?a.type?"Object"===a.type&&(s[e]=a.result):s[e]=t[e]:n.useEnable?s[e]=mergeEnableObject(s[e],t[e]):s[e]=t[e]}else t.hasOwnProperty(e)&&!s.hasOwnProperty(e)&&n.inheritMissing&&(s[e]=t[e]);if(n.useSymbol){let e=Object.getOwnPropertySymbols(t);if(e.length)for(let r of e)s[r]=t[r]}return n?.onAfterMerge?.(s,e,t),s},deepMergeArrays=(e,t,r={})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;r?.onBeforeMerge?.(e,t);const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1},r),o=a.targetClone?[...e]:e;if("replace"===a.dataMode)for(let e=0;e<t.length&&(a.inheritMissing||!(e>=o.length));e++){deepMergeHelper(o[e],t[e],a).flag||(o[e]=t[e])}else"concat"===a.dataMode||(o.length=0),o.push(...t);return r?.onAfterMerge?.(o,e,t),o},deepMergeMaps=(e,t,r={})=>{if(!(e instanceof Map&&t instanceof Map))return e;r?.onBeforeMerge?.(e,t);const a=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Map([...e]):e;for(const[e,n]of t.entries())if(o.has(e)){const t=o.get(e),r=n,s=deepMergeHelper(t,r,a);s.flag?"Object"===s.type&&o.set(e,s.result):o.set(e,r)}else r.inheritMissing&&o.set(e,n);return r?.onAfterMerge?.(o,e,t),o},deepMergeSets=(e,t,r={})=>{if(!(e instanceof Set&&t instanceof Set))return e;r?.onBeforeMerge?.(e,t);const a=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=a.targetClone?new Set(...e):e;if("replace"===a.dataMode){const e=[...o],r=[...t],n=deepMergeHelper(e,r,a);o.clear();for(let e of n.result)o.add(e)}else if("concat"===a.dataMode)for(let e of t)o.add(e);else{o.clear();for(let e of t)o.add(e)}return r?.onAfterMerge?.(o,e,t),o};return deepMergeHelper(e,t,a).result},utils={getDataType:getDataType,requireTypes:requireTypes,deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:wrapArrayMethods,arrayMutableMethods:arrayMutableMethods,setMutableMethods:setMutableMethods,mapMutableMethods:mapMutableMethods,wrapSetMethods:wrapSetMethods,wrapMapMethods:wrapMapMethods,getUniqueId:getUniqueId,deepMerge:deepMerge,shallowCopy:shallowCopy,copyObjectWithSymbol:copyObjectWithSymbol};export{utils as default};
|
package/dist/utils.umd.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
2
|
/*!
|
|
3
|
-
* @since Last modified: 2025-12-
|
|
3
|
+
* @since Last modified: 2025-12-26 9:45:49
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.14
|
|
6
6
|
* @author AXUI development team <3217728223@qq.com>
|
|
7
7
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
8
8
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -73,18 +73,26 @@
|
|
|
73
73
|
input: data,
|
|
74
74
|
type: dataType,
|
|
75
75
|
cloned: result !== data,
|
|
76
|
+
parent: opts.parent
|
|
76
77
|
});
|
|
77
78
|
return result;
|
|
78
79
|
}
|
|
79
80
|
// If interceptor returns null/undefined, continue with normal cloning process
|
|
80
81
|
}
|
|
81
82
|
// Callback before cloning
|
|
82
|
-
opts.onBeforeClone?.(
|
|
83
|
+
opts.onBeforeClone?.({
|
|
84
|
+
input: data,
|
|
85
|
+
type: dataType,
|
|
86
|
+
parent: opts.parent
|
|
87
|
+
});
|
|
83
88
|
let newData, cloned = true;
|
|
84
89
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
85
90
|
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
91
|
+
//存储parent对象,在下一次深复制时使用
|
|
92
|
+
opts.parent = data;
|
|
86
93
|
// Clone regular properties
|
|
87
94
|
for (const key in data) {
|
|
95
|
+
//临时保存父对象
|
|
88
96
|
newObj[key] = deepClone(data[key], opts);
|
|
89
97
|
}
|
|
90
98
|
// Clone Symbol properties
|
|
@@ -96,10 +104,12 @@
|
|
|
96
104
|
newData = newObj;
|
|
97
105
|
}
|
|
98
106
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
107
|
+
opts.parent = data;
|
|
99
108
|
newData = data.map(item => deepClone(item, opts));
|
|
100
109
|
}
|
|
101
110
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
102
111
|
const newMap = new Map();
|
|
112
|
+
opts.parent = data;
|
|
103
113
|
for (const [key, value] of data) {
|
|
104
114
|
// Both Map keys and values need deep cloning
|
|
105
115
|
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
@@ -108,6 +118,7 @@
|
|
|
108
118
|
}
|
|
109
119
|
else if (dataType === 'Set' && opts.cloneSet) {
|
|
110
120
|
const newSet = new Set();
|
|
121
|
+
opts.parent = data;
|
|
111
122
|
for (const value of data) {
|
|
112
123
|
// Set values need deep cloning
|
|
113
124
|
newSet.add(deepClone(value, opts));
|
|
@@ -137,6 +148,7 @@
|
|
|
137
148
|
input: data,
|
|
138
149
|
type: dataType,
|
|
139
150
|
cloned,
|
|
151
|
+
parent: opts.parent
|
|
140
152
|
});
|
|
141
153
|
return newData;
|
|
142
154
|
};
|
|
@@ -426,7 +438,20 @@
|
|
|
426
438
|
return methods;
|
|
427
439
|
};
|
|
428
440
|
|
|
429
|
-
const
|
|
441
|
+
const copyObjectWithSymbol = (data) => {
|
|
442
|
+
if (!data || typeof data !== 'object') {
|
|
443
|
+
return data;
|
|
444
|
+
}
|
|
445
|
+
// Ensure the object type includes string and symbol keys
|
|
446
|
+
const obj = data, symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
|
|
447
|
+
acc[sym] = obj[sym];
|
|
448
|
+
return acc;
|
|
449
|
+
}, {});
|
|
450
|
+
// Shallow copy the object and include the Symbol properties
|
|
451
|
+
return { ...obj, ...symbolProperties };
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
const shallowCopy = (data, options = {}) => {
|
|
430
455
|
const dataType = getDataType(data);
|
|
431
456
|
// Check if data is a Set
|
|
432
457
|
if (dataType === 'Set') {
|
|
@@ -445,13 +470,37 @@
|
|
|
445
470
|
}
|
|
446
471
|
// Check if data is a Plain Object (including Symbol keys)
|
|
447
472
|
if (dataType === 'object') {
|
|
448
|
-
|
|
449
|
-
const symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
|
|
450
|
-
acc[sym] = obj[sym];
|
|
451
|
-
return acc;
|
|
452
|
-
}, {});
|
|
473
|
+
// Ensure the object type includes string and symbol keys
|
|
453
474
|
// Shallow copy the object and include the Symbol properties
|
|
454
|
-
return
|
|
475
|
+
return copyObjectWithSymbol(data);
|
|
476
|
+
}
|
|
477
|
+
// Check if data is a Date
|
|
478
|
+
if (dataType === 'Date') {
|
|
479
|
+
return new Date(data.getTime());
|
|
480
|
+
}
|
|
481
|
+
// Check if data is a RegExp
|
|
482
|
+
if (dataType === 'RegExp') {
|
|
483
|
+
return new RegExp(data.source, data.flags);
|
|
484
|
+
}
|
|
485
|
+
// Check if data is a Buffer (for Node.js)
|
|
486
|
+
if (dataType === 'Buffer') {
|
|
487
|
+
return Buffer.from(data);
|
|
488
|
+
}
|
|
489
|
+
// Check if data is an ArrayBuffer or TypedArray
|
|
490
|
+
if (dataType === 'ArrayBuffer' || ArrayBuffer.isView(data)) {
|
|
491
|
+
return data.slice(0);
|
|
492
|
+
}
|
|
493
|
+
// Check if data is a WeakSet
|
|
494
|
+
if (dataType === 'WeakSet') {
|
|
495
|
+
return new WeakSet([...data]);
|
|
496
|
+
}
|
|
497
|
+
// Check if data is a WeakMap
|
|
498
|
+
if (dataType === 'WeakMap') {
|
|
499
|
+
return new WeakMap([...data]);
|
|
500
|
+
}
|
|
501
|
+
// Check if data is an Error
|
|
502
|
+
if (dataType === 'Error') {
|
|
503
|
+
return new Error(data.message);
|
|
455
504
|
}
|
|
456
505
|
// For other types (such as numbers, strings, booleans, etc.), return the original value
|
|
457
506
|
return data;
|
|
@@ -712,6 +761,7 @@
|
|
|
712
761
|
getUniqueId,
|
|
713
762
|
deepMerge,
|
|
714
763
|
shallowCopy,
|
|
764
|
+
copyObjectWithSymbol,
|
|
715
765
|
};
|
|
716
766
|
|
|
717
767
|
return utils;
|
package/dist/utils.umd.min.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @since Last modified: 2025-12-
|
|
2
|
+
* @since Last modified: 2025-12-26 9:45:49
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.14
|
|
5
5
|
* @author AXUI development team <3217728223@qq.com>
|
|
6
6
|
* @description This is a set of general-purpose JavaScript utility functions developed by the AXUI team. All functions are pure and do not involve CSS or other third-party libraries. They are suitable for any web front-end environment.
|
|
7
7
|
* @see {@link https://www.axui.cn|Official website}
|
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
* @copyright This software supports the MIT License, allowing free learning and commercial use, but please retain the terms 'ax,' 'axui,' 'AX,' and 'AXUI' within the software.
|
|
13
13
|
* @license MIT license
|
|
14
14
|
*/
|
|
15
|
-
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).utils=t()}(this,function(){"use strict";const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),
|
|
15
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).utils=t()}(this,function(){"use strict";const getDataType=e=>{let t,r=Object.prototype.toString.call(e).slice(8,-1);return t="Function"===r&&/^\s*class\s+/.test(e.toString())?"Class":"Object"===r&&Object.getPrototypeOf(e)!==Object.prototype?"Instance":r,t},deepClone=(e,t={})=>{const r=getDataType(e),n=Object.assign({cloneSet:!0,cloneMap:!0,cloneObject:!0,cloneArray:!0,cloneDate:!0,cloneRegex:!0},t);if(n.interceptor&&"function"==typeof n.interceptor){let t=n.interceptor(e,r);if(t)return n.onAfterClone?.({output:t,input:e,type:r,cloned:t!==e,parent:n.parent}),t}n.onBeforeClone?.({input:e,type:r,parent:n.parent});let o,a=!0;if("Object"===r&&n.cloneObject){const t={},r=Object.getOwnPropertySymbols(e);n.parent=e;for(const r in e)t[r]=deepClone(e[r],n);if(r.length>0)for(const o of r)t[o]=deepClone(e[o],n);o=t}else if("Array"===r&&n.cloneArray)n.parent=e,o=e.map(e=>deepClone(e,n));else if("Map"===r&&n.cloneMap){const t=new Map;n.parent=e;for(const[r,o]of e)t.set(deepClone(r,n),deepClone(o,n));o=t}else if("Set"===r&&n.cloneSet){const t=new Set;n.parent=e;for(const r of e)t.add(deepClone(r,n));o=t}else if("Date"===r&&n.cloneDate)o=new Date(e.getTime());else if("RegExp"===r&&n.cloneRegex){const t=e;o=new RegExp(t.source,t.flags)}else o=e,a=!1;return n.onAfterClone?.({output:o,input:e,type:r,cloned:a,parent:n.parent}),o},deepCloneToJSON=e=>{const t=getDataType(e);if("Object"===t){const t={};for(const r in e)t[r]=deepCloneToJSON(e[r]);for(const e in t)void 0===t[e]&&Reflect.deleteProperty(t,e);return t}if("Array"===t){return e.map((e,t)=>deepCloneToJSON(e)).filter(e=>void 0!==e)}return["Number","String","Boolean","Null"].includes(t)?e:void 0},e=["push","pop","shift","unshift","splice","sort","reverse","copyWithin","fill"],t=["add","delete","clear"],r=["set","delete","clear"],copyObjectWithSymbol=e=>{if(!e||"object"!=typeof e)return e;const t=e,r=Object.getOwnPropertySymbols(t).reduce((e,r)=>(e[r]=t[r],e),{});return{...t,...r}},shallowCopy=(e,t={})=>{const r=getDataType(e);return"Set"===r?new Set([...e]):"Map"===r?new Map([...e]):Array.isArray(e)?[...e]:"object"===r?copyObjectWithSymbol(e):"Date"===r?new Date(e.getTime()):"RegExp"===r?new RegExp(e.source,e.flags):"Buffer"===r?Buffer.from(e):"ArrayBuffer"===r||ArrayBuffer.isView(e)?e.slice(0):"WeakSet"===r?new WeakSet([...e]):"WeakMap"===r?new WeakMap([...e]):"Error"===r?new Error(e.message):e};return{getDataType:getDataType,requireTypes:(e,t,r)=>{let n=Array.isArray(t)?t:[t],o=getDataType(e),a=o.toLowerCase(),s=n.map(e=>e.toLowerCase()),i=a.includes("html")?"element":a;if(r)try{if(!s.includes(i))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${i}`)}catch(e){r(e,o)}else if(!s.includes(i))throw new TypeError(`Expected data type(s): [${s.join(", ")}], but got: ${i}`);return o},deepClone:deepClone,deepCloneToJSON:deepCloneToJSON,wrapArrayMethods:({target:t,onBeforeMutate:r=()=>{},onAfterMutate:n=()=>{},allowList:o,props:a={}})=>{if(!Array.isArray(t))throw new TypeError("The 'target' parameter must be an array.");o&&!o?.length||(o=e);const s={};for(let e of o)s[e]=function(...o){const s={},i=t.length;switch(e){case"push":case"unshift":s.addedItems=[...o];break;case"pop":s.poppedItem=t[i-1];break;case"shift":s.shiftedItem=t[0];break;case"splice":const[e,r]=o,n=e<0?Math.max(i+e,0):Math.min(e,i),a=void 0===r?i-n:r;s.deletedItems=t.slice(n,n+a);break;case"sort":case"reverse":s.oldSnapshot=[...t];break;case"fill":case"copyWithin":const l=o[1]||0,c=void 0===o[2]?i:o[2];s.oldItems=t.slice(l,c),s.start=l,s.end=c}r?.(s);const l=Array.prototype[e].apply(t,o),c={value:l,key:e,args:o,context:s,target:t,...a};return n?.(c),l};return s},arrayMutableMethods:e,setMutableMethods:t,mapMutableMethods:r,wrapSetMethods:({target:e,onBeforeMutate:r=()=>{},onAfterMutate:n=()=>{},allowList:o=t,props:a={}})=>{if(!(e instanceof Set))throw new TypeError("The 'target' parameter must be a Set.");const s={},createWrappedMethod=t=>function(...o){const s={};switch(t){case"add":{const[t]=o;s.addedItem=t,s.existed=e.has(t);break}case"delete":{const[t]=o;s.existed=e.has(t),s.deletedItem=s.existed?t:void 0;break}case"clear":s.clearedItems=Array.from(e),s.previousSize=e.size}r(s);const i=e[t].apply(e,o),l={method:t,result:i,args:o,context:s,target:e,...a};return n(l),i};for(const e of o)t.includes(e)&&(s[e]=createWrappedMethod(e));return Object.defineProperty(s,"target",{get:()=>e,enumerable:!1,configurable:!1}),s},wrapMapMethods:({target:e,onBeforeMutate:t=()=>{},onAfterMutate:n=()=>{},allowList:o=r,props:a={}})=>{if(!(e instanceof Map))throw new TypeError("The 'target' parameter must be a Map.");const s={},createWrappedMethod=r=>function(...o){const s={};switch(r){case"set":{const[t,r]=o;s.key=t,s.newValue=r,s.existed=e.has(t),s.oldValue=s.existed?e.get(t):void 0;break}case"delete":{const[t]=o;s.key=t,s.existed=e.has(t),s.value=s.existed?e.get(t):void 0;break}case"clear":s.clearedItems=Array.from(e.entries()),s.previousSize=e.size}t(s);const i=e[r].apply(e,o),l={method:r,result:i,args:o,context:s,target:e,...a};return n(l),i};for(const e of o)r.includes(e)&&(s[e]=createWrappedMethod(e));return Object.defineProperty(s,"target",{get:()=>e,enumerable:!1,configurable:!1}),s},getUniqueId:(e={})=>{const t=e.prefix,r=e.suffix,n=e.base10,o=e.base36;return`${t?t+"-":""}${Date.now()}${o?"-"+Math.random().toString(36).substring(2,11):""}${n?"-"+Math.floor(1e4*Math.random()).toString().padStart(4,"0"):""}${r?"-"+r:""}`},deepMerge:(e,t,r={})=>{const n=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0,useSymbol:!0,deepClone:{},onBeforeMerge:void 0,onAfterMerge:void 0},r),deepMergeHelper=(e,t,r)=>{let n,o,a=getDataType(e),s=getDataType(t),i=!0;return"Object"===a&&"Object"===s?(o=deepMergeObjects(e,t,r),n="Object"):"Array"===a&&"Array"===s?(o=deepMergeArrays(e,t,r),n="Array"):"Set"===a&&"Set"===s?(o=deepMergeSets(e,t,r),n="Set"):"Map"===a&&"Map"===s?(o=deepMergeMaps(e,t,r),n="Map"):(i=!1,o=e),{result:o,flag:i,type:n}},mergeEnableObject=(e,t)=>e?.hasOwnProperty("enable")&&"boolean"==typeof t?(e.enable=t,e):t?.hasOwnProperty("enable")&&"boolean"==typeof e?Object.assign({enable:e},t):t,deepMergeObjects=(e,t,r={})=>{let n=getDataType(e),o=getDataType(t);if("Object"!==n||"Object"!==o)return e;r?.onBeforeMerge?.(e,t);const a=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r);let s={};s=a.targetClone?shallowCopy(e):e;for(let e in t)if(t.hasOwnProperty(e)&&s.hasOwnProperty(e)){let n=deepMergeHelper(s[e],t[e],r);n.flag?n.type?"Object"===n.type&&(s[e]=n.result):s[e]=t[e]:a.useEnable?s[e]=mergeEnableObject(s[e],t[e]):s[e]=t[e]}else t.hasOwnProperty(e)&&!s.hasOwnProperty(e)&&a.inheritMissing&&(s[e]=t[e]);if(a.useSymbol){let e=Object.getOwnPropertySymbols(t);if(e.length)for(let r of e)s[r]=t[r]}return a?.onAfterMerge?.(s,e,t),s},deepMergeArrays=(e,t,r={})=>{if(!Array.isArray(e)||!Array.isArray(t))return e;r?.onBeforeMerge?.(e,t);const n=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1},r),o=n.targetClone?[...e]:e;if("replace"===n.dataMode)for(let e=0;e<t.length&&(n.inheritMissing||!(e>=o.length));e++){deepMergeHelper(o[e],t[e],n).flag||(o[e]=t[e])}else"concat"===n.dataMode||(o.length=0),o.push(...t);return r?.onAfterMerge?.(o,e,t),o},deepMergeMaps=(e,t,r={})=>{if(!(e instanceof Map&&t instanceof Map))return e;r?.onBeforeMerge?.(e,t);const n=Object.assign({inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=n.targetClone?new Map([...e]):e;for(const[e,a]of t.entries())if(o.has(e)){const t=o.get(e),r=a,s=deepMergeHelper(t,r,n);s.flag?"Object"===s.type&&o.set(e,s.result):o.set(e,r)}else r.inheritMissing&&o.set(e,a);return r?.onAfterMerge?.(o,e,t),o},deepMergeSets=(e,t,r={})=>{if(!(e instanceof Set&&t instanceof Set))return e;r?.onBeforeMerge?.(e,t);const n=Object.assign({dataMode:"clear",inheritMissing:!0,targetClone:!1,useEnable:!0},r),o=n.targetClone?new Set(...e):e;if("replace"===n.dataMode){const e=[...o],r=[...t],a=deepMergeHelper(e,r,n);o.clear();for(let e of a.result)o.add(e)}else if("concat"===n.dataMode)for(let e of t)o.add(e);else{o.clear();for(let e of t)o.add(e)}return r?.onAfterMerge?.(o,e,t),o};return deepMergeHelper(e,t,n).result},shallowCopy:shallowCopy,copyObjectWithSymbol:copyObjectWithSymbol}});
|
package/dist.zip
CHANGED
|
Binary file
|