@codady/utils 0.0.13 → 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 +18 -0
- package/dist/utils.cjs.js +15 -3
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +15 -3
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +15 -3
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/package.json +1 -1
- package/src/deepClone.js +14 -2
- package/src/deepClone.ts +36 -14
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
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
|
+
|
|
6
24
|
## [v0.0.13] - 2025-12-25
|
|
7
25
|
|
|
8
26
|
### 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
|
};
|
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
|
};
|
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
|
};
|
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
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codady/utils",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"author": "AXUI Development Team",
|
|
5
5
|
"license": "MIT",
|
|
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.",
|
package/src/deepClone.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/26 09:45:33
|
|
3
3
|
* Deep clone an array, object, or other cloneable data types.
|
|
4
4
|
*
|
|
5
5
|
* Features:
|
|
@@ -108,18 +108,26 @@ const deepClone = (data, options = {}) => {
|
|
|
108
108
|
input: data,
|
|
109
109
|
type: dataType,
|
|
110
110
|
cloned: result !== data,
|
|
111
|
+
parent: opts.parent
|
|
111
112
|
});
|
|
112
113
|
return result;
|
|
113
114
|
}
|
|
114
115
|
// If interceptor returns null/undefined, continue with normal cloning process
|
|
115
116
|
}
|
|
116
117
|
// Callback before cloning
|
|
117
|
-
opts.onBeforeClone?.(
|
|
118
|
+
opts.onBeforeClone?.({
|
|
119
|
+
input: data,
|
|
120
|
+
type: dataType,
|
|
121
|
+
parent: opts.parent
|
|
122
|
+
});
|
|
118
123
|
let newData, cloned = true;
|
|
119
124
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
120
125
|
const newObj = {}, symbols = Object.getOwnPropertySymbols(data);
|
|
126
|
+
//存储parent对象,在下一次深复制时使用
|
|
127
|
+
opts.parent = data;
|
|
121
128
|
// Clone regular properties
|
|
122
129
|
for (const key in data) {
|
|
130
|
+
//临时保存父对象
|
|
123
131
|
newObj[key] = deepClone(data[key], opts);
|
|
124
132
|
}
|
|
125
133
|
// Clone Symbol properties
|
|
@@ -131,10 +139,12 @@ const deepClone = (data, options = {}) => {
|
|
|
131
139
|
newData = newObj;
|
|
132
140
|
}
|
|
133
141
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
142
|
+
opts.parent = data;
|
|
134
143
|
newData = data.map(item => deepClone(item, opts));
|
|
135
144
|
}
|
|
136
145
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
137
146
|
const newMap = new Map();
|
|
147
|
+
opts.parent = data;
|
|
138
148
|
for (const [key, value] of data) {
|
|
139
149
|
// Both Map keys and values need deep cloning
|
|
140
150
|
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
@@ -143,6 +153,7 @@ const deepClone = (data, options = {}) => {
|
|
|
143
153
|
}
|
|
144
154
|
else if (dataType === 'Set' && opts.cloneSet) {
|
|
145
155
|
const newSet = new Set();
|
|
156
|
+
opts.parent = data;
|
|
146
157
|
for (const value of data) {
|
|
147
158
|
// Set values need deep cloning
|
|
148
159
|
newSet.add(deepClone(value, opts));
|
|
@@ -172,6 +183,7 @@ const deepClone = (data, options = {}) => {
|
|
|
172
183
|
input: data,
|
|
173
184
|
type: dataType,
|
|
174
185
|
cloned,
|
|
186
|
+
parent: opts.parent
|
|
175
187
|
});
|
|
176
188
|
return newData;
|
|
177
189
|
};
|
package/src/deepClone.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/26 09:45:33
|
|
3
3
|
* Deep clone an array, object, or other cloneable data types.
|
|
4
4
|
*
|
|
5
5
|
* Features:
|
|
@@ -96,16 +96,24 @@ export interface DeepCloneOptions {
|
|
|
96
96
|
*/
|
|
97
97
|
interceptor?: <T>(data: T, dataType: string) => T | null | undefined;
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
/**
|
|
100
100
|
* Callback before cloning.
|
|
101
101
|
*/
|
|
102
|
-
onBeforeClone?: (
|
|
102
|
+
onBeforeClone?: (result: BeforeCloneResult) => void;
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
105
|
* Callback after cloning.
|
|
106
106
|
* @param result Object containing cloning result.
|
|
107
107
|
*/
|
|
108
108
|
onAfterClone?: (result: AfterCloneResult) => void;
|
|
109
|
+
|
|
110
|
+
//深度复制时的临时保存的父对象
|
|
111
|
+
parent?: Record<string | symbol, any> | Map<any, any> | Set<any> | any[] | null;
|
|
112
|
+
}
|
|
113
|
+
export interface BeforeCloneResult {
|
|
114
|
+
input: any;
|
|
115
|
+
type: string;
|
|
116
|
+
parent?: Record<string | symbol, any> | Map<any, any> | Set<any> | any[] | null;
|
|
109
117
|
}
|
|
110
118
|
export interface AfterCloneResult<T = any> {
|
|
111
119
|
// Cloned data
|
|
@@ -116,6 +124,7 @@ export interface AfterCloneResult<T = any> {
|
|
|
116
124
|
type: string;
|
|
117
125
|
// Whether cloning was performed
|
|
118
126
|
cloned: boolean;
|
|
127
|
+
parent?: Record<string | symbol, any> | Map<any, any> | Set<any> | any[] | null;
|
|
119
128
|
}
|
|
120
129
|
//支持原始值的复制,包括Number、String、Boolean、Null
|
|
121
130
|
//支持Date和Regex对象值复制(值转换)
|
|
@@ -146,6 +155,7 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
146
155
|
input: data,
|
|
147
156
|
type: dataType,
|
|
148
157
|
cloned: result !== data,
|
|
158
|
+
parent: opts.parent
|
|
149
159
|
});
|
|
150
160
|
return result as T;
|
|
151
161
|
}
|
|
@@ -153,41 +163,52 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
153
163
|
}
|
|
154
164
|
|
|
155
165
|
// Callback before cloning
|
|
156
|
-
opts.onBeforeClone?.(
|
|
166
|
+
opts.onBeforeClone?.({
|
|
167
|
+
input: data,
|
|
168
|
+
type: dataType,
|
|
169
|
+
parent: opts.parent
|
|
170
|
+
});
|
|
157
171
|
|
|
158
|
-
let newData,
|
|
172
|
+
let newData: any,
|
|
159
173
|
cloned = true;
|
|
160
174
|
|
|
161
175
|
if (dataType === 'Object' && opts.cloneObject) {
|
|
162
176
|
const newObj: Record<string | symbol, any> = {},
|
|
163
177
|
symbols = Object.getOwnPropertySymbols(data);
|
|
164
178
|
|
|
179
|
+
//存储parent对象,在下一次深复制时使用
|
|
180
|
+
opts.parent = data as any;
|
|
181
|
+
|
|
165
182
|
// Clone regular properties
|
|
166
183
|
for (const key in data) {
|
|
167
|
-
|
|
184
|
+
//临时保存父对象
|
|
185
|
+
newObj[key] = deepClone((data as any)[key], opts);
|
|
168
186
|
}
|
|
169
187
|
|
|
170
188
|
// Clone Symbol properties
|
|
171
189
|
if (symbols.length > 0) {
|
|
172
190
|
for (const symbol of symbols) {
|
|
173
|
-
newObj[symbol] = deepClone((data as any)[symbol],opts);
|
|
191
|
+
newObj[symbol] = deepClone((data as any)[symbol], opts);
|
|
174
192
|
}
|
|
175
193
|
}
|
|
176
194
|
newData = newObj as T;
|
|
177
195
|
} else if (dataType === 'Array' && opts.cloneArray) {
|
|
178
|
-
|
|
196
|
+
opts.parent = data as any;
|
|
197
|
+
newData = (data as any[]).map(item => deepClone(item, opts)) as T;
|
|
179
198
|
} else if (dataType === 'Map' && opts.cloneMap) {
|
|
180
199
|
const newMap = new Map();
|
|
200
|
+
opts.parent = data as any;
|
|
181
201
|
for (const [key, value] of data as Map<any, any>) {
|
|
182
202
|
// Both Map keys and values need deep cloning
|
|
183
|
-
newMap.set(deepClone(key,opts), deepClone(value,opts));
|
|
203
|
+
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
184
204
|
}
|
|
185
205
|
newData = newMap as T;
|
|
186
206
|
} else if (dataType === 'Set' && opts.cloneSet) {
|
|
187
207
|
const newSet = new Set();
|
|
208
|
+
opts.parent = data as any;
|
|
188
209
|
for (const value of data as Set<any>) {
|
|
189
210
|
// Set values need deep cloning
|
|
190
|
-
newSet.add(deepClone(value,opts));
|
|
211
|
+
newSet.add(deepClone(value, opts));
|
|
191
212
|
}
|
|
192
213
|
newData = newSet as T;
|
|
193
214
|
} else if (dataType === 'Date' && opts.cloneDate) {
|
|
@@ -195,11 +216,11 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
195
216
|
} else if (dataType === 'RegExp' && opts.cloneRegex) {
|
|
196
217
|
const regex = data as RegExp;
|
|
197
218
|
newData = new RegExp(regex.source, regex.flags) as T;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
219
|
+
// } else if ((dataType.includes('HTML') && opts.cloneElement) ||
|
|
220
|
+
// (dataType === 'DocumentFragment' && opts.cloneFragment)
|
|
221
|
+
//) {
|
|
201
222
|
//Text,Comment,HTML*Element,DocumentFragment,Attr
|
|
202
|
-
|
|
223
|
+
// newData = (data as any).cloneNode(true) as T;
|
|
203
224
|
} else {
|
|
204
225
|
// Number, String, Boolean, Symbol, Function,Error,Promise,ArrayBuffer,Blob,File, return directly
|
|
205
226
|
newData = data;
|
|
@@ -211,6 +232,7 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
211
232
|
input: data,
|
|
212
233
|
type: dataType,
|
|
213
234
|
cloned,
|
|
235
|
+
parent: opts.parent
|
|
214
236
|
});
|
|
215
237
|
return newData;
|
|
216
238
|
};
|