@codady/utils 0.0.13 → 0.0.15
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 +14 -7
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +14 -7
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +14 -7
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/package.json +1 -1
- package/src/deepClone.js +13 -6
- package/src/deepClone.ts +30 -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 11:26:20
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.15
|
|
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,36 +69,42 @@ 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);
|
|
82
87
|
// Clone regular properties
|
|
83
88
|
for (const key in data) {
|
|
89
|
+
//临时保存父对象
|
|
84
90
|
newObj[key] = deepClone(data[key], opts);
|
|
85
91
|
}
|
|
86
92
|
// Clone Symbol properties
|
|
87
93
|
if (symbols.length > 0) {
|
|
88
94
|
for (const symbol of symbols) {
|
|
89
|
-
newObj[symbol] = deepClone(data[symbol], opts);
|
|
95
|
+
newObj[symbol] = deepClone(data[symbol], { ...opts, parent: data });
|
|
90
96
|
}
|
|
91
97
|
}
|
|
92
98
|
newData = newObj;
|
|
93
99
|
}
|
|
94
100
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
95
|
-
newData = data.map(item => deepClone(item, opts));
|
|
101
|
+
newData = data.map(item => deepClone(item, { ...opts, parent: data }));
|
|
96
102
|
}
|
|
97
103
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
98
104
|
const newMap = new Map();
|
|
99
105
|
for (const [key, value] of data) {
|
|
100
106
|
// Both Map keys and values need deep cloning
|
|
101
|
-
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
107
|
+
newMap.set(deepClone(key, opts), deepClone(value, { ...opts, parent: data }));
|
|
102
108
|
}
|
|
103
109
|
newData = newMap;
|
|
104
110
|
}
|
|
@@ -106,7 +112,7 @@ const deepClone = (data, options = {}) => {
|
|
|
106
112
|
const newSet = new Set();
|
|
107
113
|
for (const value of data) {
|
|
108
114
|
// Set values need deep cloning
|
|
109
|
-
newSet.add(deepClone(value, opts));
|
|
115
|
+
newSet.add(deepClone(value, { ...opts, parent: data }));
|
|
110
116
|
}
|
|
111
117
|
newData = newSet;
|
|
112
118
|
}
|
|
@@ -133,6 +139,7 @@ const deepClone = (data, options = {}) => {
|
|
|
133
139
|
input: data,
|
|
134
140
|
type: dataType,
|
|
135
141
|
cloned,
|
|
142
|
+
parent: opts.parent
|
|
136
143
|
});
|
|
137
144
|
return newData;
|
|
138
145
|
};
|
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 11:26:20
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.15
|
|
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(
|
|
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);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,parent:e});a=t}else if("Array"===r&&o.cloneArray)a=e.map(t=>deepClone(t,{...o,parent:e}));else if("Map"===r&&o.cloneMap){const t=new Map;for(const[r,a]of e)t.set(deepClone(r,o),deepClone(a,{...o,parent:e}));a=t}else if("Set"===r&&o.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,{...o,parent:e}));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 11:26:20
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.15
|
|
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,36 +67,42 @@ 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);
|
|
80
85
|
// Clone regular properties
|
|
81
86
|
for (const key in data) {
|
|
87
|
+
//临时保存父对象
|
|
82
88
|
newObj[key] = deepClone(data[key], opts);
|
|
83
89
|
}
|
|
84
90
|
// Clone Symbol properties
|
|
85
91
|
if (symbols.length > 0) {
|
|
86
92
|
for (const symbol of symbols) {
|
|
87
|
-
newObj[symbol] = deepClone(data[symbol], opts);
|
|
93
|
+
newObj[symbol] = deepClone(data[symbol], { ...opts, parent: data });
|
|
88
94
|
}
|
|
89
95
|
}
|
|
90
96
|
newData = newObj;
|
|
91
97
|
}
|
|
92
98
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
93
|
-
newData = data.map(item => deepClone(item, opts));
|
|
99
|
+
newData = data.map(item => deepClone(item, { ...opts, parent: data }));
|
|
94
100
|
}
|
|
95
101
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
96
102
|
const newMap = new Map();
|
|
97
103
|
for (const [key, value] of data) {
|
|
98
104
|
// Both Map keys and values need deep cloning
|
|
99
|
-
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
105
|
+
newMap.set(deepClone(key, opts), deepClone(value, { ...opts, parent: data }));
|
|
100
106
|
}
|
|
101
107
|
newData = newMap;
|
|
102
108
|
}
|
|
@@ -104,7 +110,7 @@ const deepClone = (data, options = {}) => {
|
|
|
104
110
|
const newSet = new Set();
|
|
105
111
|
for (const value of data) {
|
|
106
112
|
// Set values need deep cloning
|
|
107
|
-
newSet.add(deepClone(value, opts));
|
|
113
|
+
newSet.add(deepClone(value, { ...opts, parent: data }));
|
|
108
114
|
}
|
|
109
115
|
newData = newSet;
|
|
110
116
|
}
|
|
@@ -131,6 +137,7 @@ const deepClone = (data, options = {}) => {
|
|
|
131
137
|
input: data,
|
|
132
138
|
type: dataType,
|
|
133
139
|
cloned,
|
|
140
|
+
parent: opts.parent
|
|
134
141
|
});
|
|
135
142
|
return newData;
|
|
136
143
|
};
|
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 11:26:20
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.15
|
|
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);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,parent:e});o=t}else if("Array"===r&&a.cloneArray)o=e.map(t=>deepClone(t,{...a,parent:e}));else if("Map"===r&&a.cloneMap){const t=new Map;for(const[r,o]of e)t.set(deepClone(r,a),deepClone(o,{...a,parent:e}));o=t}else if("Set"===r&&a.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,{...a,parent:e}));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 11:26:20
|
|
4
4
|
* @name Utils for web front-end.
|
|
5
|
-
* @version 0.0.
|
|
5
|
+
* @version 0.0.15
|
|
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,36 +73,42 @@
|
|
|
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);
|
|
86
91
|
// Clone regular properties
|
|
87
92
|
for (const key in data) {
|
|
93
|
+
//临时保存父对象
|
|
88
94
|
newObj[key] = deepClone(data[key], opts);
|
|
89
95
|
}
|
|
90
96
|
// Clone Symbol properties
|
|
91
97
|
if (symbols.length > 0) {
|
|
92
98
|
for (const symbol of symbols) {
|
|
93
|
-
newObj[symbol] = deepClone(data[symbol], opts);
|
|
99
|
+
newObj[symbol] = deepClone(data[symbol], { ...opts, parent: data });
|
|
94
100
|
}
|
|
95
101
|
}
|
|
96
102
|
newData = newObj;
|
|
97
103
|
}
|
|
98
104
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
99
|
-
newData = data.map(item => deepClone(item, opts));
|
|
105
|
+
newData = data.map(item => deepClone(item, { ...opts, parent: data }));
|
|
100
106
|
}
|
|
101
107
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
102
108
|
const newMap = new Map();
|
|
103
109
|
for (const [key, value] of data) {
|
|
104
110
|
// Both Map keys and values need deep cloning
|
|
105
|
-
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
111
|
+
newMap.set(deepClone(key, opts), deepClone(value, { ...opts, parent: data }));
|
|
106
112
|
}
|
|
107
113
|
newData = newMap;
|
|
108
114
|
}
|
|
@@ -110,7 +116,7 @@
|
|
|
110
116
|
const newSet = new Set();
|
|
111
117
|
for (const value of data) {
|
|
112
118
|
// Set values need deep cloning
|
|
113
|
-
newSet.add(deepClone(value, opts));
|
|
119
|
+
newSet.add(deepClone(value, { ...opts, parent: data }));
|
|
114
120
|
}
|
|
115
121
|
newData = newSet;
|
|
116
122
|
}
|
|
@@ -137,6 +143,7 @@
|
|
|
137
143
|
input: data,
|
|
138
144
|
type: dataType,
|
|
139
145
|
cloned,
|
|
146
|
+
parent: opts.parent
|
|
140
147
|
});
|
|
141
148
|
return newData;
|
|
142
149
|
};
|
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 11:26:20
|
|
3
3
|
* @name Utils for web front-end.
|
|
4
|
-
* @version 0.0.
|
|
4
|
+
* @version 0.0.15
|
|
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);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,parent:e});o=t}else if("Array"===r&&n.cloneArray)o=e.map(t=>deepClone(t,{...n,parent:e}));else if("Map"===r&&n.cloneMap){const t=new Map;for(const[r,o]of e)t.set(deepClone(r,n),deepClone(o,{...n,parent:e}));o=t}else if("Set"===r&&n.cloneSet){const t=new Set;for(const r of e)t.add(deepClone(r,{...n,parent:e}));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.15",
|
|
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 11:26:10
|
|
3
3
|
* Deep clone an array, object, or other cloneable data types.
|
|
4
4
|
*
|
|
5
5
|
* Features:
|
|
@@ -108,36 +108,42 @@ 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);
|
|
121
126
|
// Clone regular properties
|
|
122
127
|
for (const key in data) {
|
|
128
|
+
//临时保存父对象
|
|
123
129
|
newObj[key] = deepClone(data[key], opts);
|
|
124
130
|
}
|
|
125
131
|
// Clone Symbol properties
|
|
126
132
|
if (symbols.length > 0) {
|
|
127
133
|
for (const symbol of symbols) {
|
|
128
|
-
newObj[symbol] = deepClone(data[symbol], opts);
|
|
134
|
+
newObj[symbol] = deepClone(data[symbol], { ...opts, parent: data });
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
137
|
newData = newObj;
|
|
132
138
|
}
|
|
133
139
|
else if (dataType === 'Array' && opts.cloneArray) {
|
|
134
|
-
newData = data.map(item => deepClone(item, opts));
|
|
140
|
+
newData = data.map(item => deepClone(item, { ...opts, parent: data }));
|
|
135
141
|
}
|
|
136
142
|
else if (dataType === 'Map' && opts.cloneMap) {
|
|
137
143
|
const newMap = new Map();
|
|
138
144
|
for (const [key, value] of data) {
|
|
139
145
|
// Both Map keys and values need deep cloning
|
|
140
|
-
newMap.set(deepClone(key, opts), deepClone(value, opts));
|
|
146
|
+
newMap.set(deepClone(key, opts), deepClone(value, { ...opts, parent: data }));
|
|
141
147
|
}
|
|
142
148
|
newData = newMap;
|
|
143
149
|
}
|
|
@@ -145,7 +151,7 @@ const deepClone = (data, options = {}) => {
|
|
|
145
151
|
const newSet = new Set();
|
|
146
152
|
for (const value of data) {
|
|
147
153
|
// Set values need deep cloning
|
|
148
|
-
newSet.add(deepClone(value, opts));
|
|
154
|
+
newSet.add(deepClone(value, { ...opts, parent: data }));
|
|
149
155
|
}
|
|
150
156
|
newData = newSet;
|
|
151
157
|
}
|
|
@@ -172,6 +178,7 @@ const deepClone = (data, options = {}) => {
|
|
|
172
178
|
input: data,
|
|
173
179
|
type: dataType,
|
|
174
180
|
cloned,
|
|
181
|
+
parent: opts.parent
|
|
175
182
|
});
|
|
176
183
|
return newData;
|
|
177
184
|
};
|
package/src/deepClone.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/26 11:26:10
|
|
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,9 +163,13 @@ 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) {
|
|
@@ -164,30 +178,31 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
164
178
|
|
|
165
179
|
// Clone regular properties
|
|
166
180
|
for (const key in data) {
|
|
167
|
-
|
|
181
|
+
//临时保存父对象
|
|
182
|
+
newObj[key] = deepClone((data as any)[key], opts);
|
|
168
183
|
}
|
|
169
184
|
|
|
170
185
|
// Clone Symbol properties
|
|
171
186
|
if (symbols.length > 0) {
|
|
172
187
|
for (const symbol of symbols) {
|
|
173
|
-
newObj[symbol] = deepClone((data as any)[symbol],opts);
|
|
188
|
+
newObj[symbol] = deepClone((data as any)[symbol], {...opts,parent:data as any});
|
|
174
189
|
}
|
|
175
190
|
}
|
|
176
191
|
newData = newObj as T;
|
|
177
192
|
} else if (dataType === 'Array' && opts.cloneArray) {
|
|
178
|
-
newData = (data as any[]).map(item => deepClone(item,opts)) as T;
|
|
193
|
+
newData = (data as any[]).map(item => deepClone(item, {...opts,parent:data as any})) as T;
|
|
179
194
|
} else if (dataType === 'Map' && opts.cloneMap) {
|
|
180
195
|
const newMap = new Map();
|
|
181
196
|
for (const [key, value] of data as Map<any, any>) {
|
|
182
197
|
// Both Map keys and values need deep cloning
|
|
183
|
-
newMap.set(deepClone(key,opts), deepClone(value,opts));
|
|
198
|
+
newMap.set(deepClone(key, opts), deepClone(value, {...opts,parent:data as any}));
|
|
184
199
|
}
|
|
185
200
|
newData = newMap as T;
|
|
186
201
|
} else if (dataType === 'Set' && opts.cloneSet) {
|
|
187
202
|
const newSet = new Set();
|
|
188
203
|
for (const value of data as Set<any>) {
|
|
189
204
|
// Set values need deep cloning
|
|
190
|
-
newSet.add(deepClone(value,opts));
|
|
205
|
+
newSet.add(deepClone(value, {...opts,parent:data as any}));
|
|
191
206
|
}
|
|
192
207
|
newData = newSet as T;
|
|
193
208
|
} else if (dataType === 'Date' && opts.cloneDate) {
|
|
@@ -195,11 +210,11 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
195
210
|
} else if (dataType === 'RegExp' && opts.cloneRegex) {
|
|
196
211
|
const regex = data as RegExp;
|
|
197
212
|
newData = new RegExp(regex.source, regex.flags) as T;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
213
|
+
// } else if ((dataType.includes('HTML') && opts.cloneElement) ||
|
|
214
|
+
// (dataType === 'DocumentFragment' && opts.cloneFragment)
|
|
215
|
+
//) {
|
|
201
216
|
//Text,Comment,HTML*Element,DocumentFragment,Attr
|
|
202
|
-
|
|
217
|
+
// newData = (data as any).cloneNode(true) as T;
|
|
203
218
|
} else {
|
|
204
219
|
// Number, String, Boolean, Symbol, Function,Error,Promise,ArrayBuffer,Blob,File, return directly
|
|
205
220
|
newData = data;
|
|
@@ -211,6 +226,7 @@ const deepClone = <T>(data: T, options: DeepCloneOptions = {}): T => {
|
|
|
211
226
|
input: data,
|
|
212
227
|
type: dataType,
|
|
213
228
|
cloned,
|
|
229
|
+
parent: opts.parent
|
|
214
230
|
});
|
|
215
231
|
return newData;
|
|
216
232
|
};
|