@codady/utils 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/modules.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Last modified: 2025/12/25 12:08:43
2
+ * Last modified: 2025/12/25 14:29:40
3
3
  */
4
4
  'use strict';
5
5
  import deepClone from './src/deepClone';
@@ -15,6 +15,7 @@ import wrapSetMethods from './src/wrapSetMethods';
15
15
  import wrapMapMethods from './src/wrapMapMethods';
16
16
  import deepMerge from './src/deepMerge';
17
17
  import shallowCopy from './src/shallowCopy';
18
+ import copyObjectWithSymbol from './src/copyObjectWithSymbol';
18
19
  const utils = {
19
20
  //executeStr,
20
21
  getDataType,
@@ -32,5 +33,6 @@ const utils = {
32
33
  getUniqueId,
33
34
  deepMerge,
34
35
  shallowCopy,
36
+ copyObjectWithSymbol,
35
37
  };
36
38
  export default utils;
package/modules.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Last modified: 2025/12/25 12:08:43
2
+ * Last modified: 2025/12/25 14:29:40
3
3
  */
4
4
  'use strict'
5
5
  import deepClone from './src/deepClone';
@@ -23,6 +23,7 @@ import deepMergeObjects from './src/deepMergeObjects';
23
23
  import deepMergeSets from './src/deepMergeSets';
24
24
  import deepEqual from './src/deepEqual';
25
25
  import shallowCopy from './src/shallowCopy';
26
+ import copyObjectWithSymbol from './src/copyObjectWithSymbol';
26
27
 
27
28
 
28
29
 
@@ -43,6 +44,7 @@ const utils = {
43
44
  getUniqueId,
44
45
  deepMerge,
45
46
  shallowCopy,
47
+ copyObjectWithSymbol,
46
48
 
47
49
  };
48
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codady/utils",
3
- "version": "0.0.12",
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.",
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Shallow copies an object, including both string keys and Symbol keys.
3
+ * 浅复制对象,包括字符串键和Symbol键
4
+ *
5
+ * @param data The source object to copy
6
+ * @returns A new object with all enumerable properties (both string and Symbol keys)
7
+ *
8
+ * @example
9
+ * const sym = Symbol('test');
10
+ * const obj = { a: 1, [sym]: 'symbol value' };
11
+ * const copy = copyObjectWithSymbol(obj);
12
+ * // copy = { a: 1, [Symbol('test')]: 'symbol value' }
13
+ */
14
+ const copyObjectWithSymbol = (data) => {
15
+ if (!data || typeof data !== 'object') {
16
+ return data;
17
+ }
18
+ // Ensure the object type includes string and symbol keys
19
+ const obj = data, symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
20
+ acc[sym] = obj[sym];
21
+ return acc;
22
+ }, {});
23
+ // Shallow copy the object and include the Symbol properties
24
+ return { ...obj, ...symbolProperties };
25
+ };
26
+ export default copyObjectWithSymbol;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Shallow copies an object, including both string keys and Symbol keys.
3
+ * 浅复制对象,包括字符串键和Symbol键
4
+ *
5
+ * @param data The source object to copy
6
+ * @returns A new object with all enumerable properties (both string and Symbol keys)
7
+ *
8
+ * @example
9
+ * const sym = Symbol('test');
10
+ * const obj = { a: 1, [sym]: 'symbol value' };
11
+ * const copy = copyObjectWithSymbol(obj);
12
+ * // copy = { a: 1, [Symbol('test')]: 'symbol value' }
13
+ */
14
+ const copyObjectWithSymbol = <T extends Record<string | symbol, any>>(data: T): T => {
15
+ if (!data || typeof data !== 'object') {
16
+ return data;
17
+ }
18
+ // Ensure the object type includes string and symbol keys
19
+ const obj = data as { [key: string | symbol]: any },
20
+ symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc: { [key: symbol]: any }, sym: symbol) => {
21
+ acc[sym] = obj[sym];
22
+ return acc;
23
+ }, {});
24
+
25
+ // Shallow copy the object and include the Symbol properties
26
+ return { ...obj, ...symbolProperties } as T;
27
+ }
28
+ export default copyObjectWithSymbol;
package/src/deepClone.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @since Last modified: 2025/12/24 17:05:29
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?.(data, dataType);
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/24 17:05:29
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?: (data: any, dataType: string) => void;
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?.(data, dataType);
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
- newObj[key] = deepClone((data as any)[key],opts);
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
- newData = (data as any[]).map(item => deepClone(item,opts)) as T;
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
- // } else if ((dataType.includes('HTML') && opts.cloneElement) ||
199
- // (dataType === 'DocumentFragment' && opts.cloneFragment)
200
- //) {
219
+ // } else if ((dataType.includes('HTML') && opts.cloneElement) ||
220
+ // (dataType === 'DocumentFragment' && opts.cloneFragment)
221
+ //) {
201
222
  //Text,Comment,HTML*Element,DocumentFragment,Attr
202
- // newData = (data as any).cloneNode(true) as T;
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
  };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @since Last modified: 2025/12/16 09:00:41
3
+ * @function getDataType
4
+ * @description Get object type.Can detect object types such as Array, Object, Function,
5
+ * Window,Location,History,Navigator,XMLHttpRequest, WebSocket,FileReader,MediaStream
6
+ * Class , String, Number, Boolean, Date, Symbol ,File ,Blob,
7
+ * Error,Promise,ArrayBuffer,TypedArray, Set, weakSet, Map, weakMap, Null, Undefined,
8
+ * Text, DocumentFragment,Comment, XMLDocument, ProcessingInstruction, Range, TreeWalker,
9
+ * NodeIterator,SVGSVGElement,MathMLElement, HTMLxxxElement (Dom nodes all contain HTML),Promise,AsyncFunction and Instance.
10
+ * @param {*} obj - Can be any object
11
+ * @returns {string} - Returns the name of the data type.
12
+ */
13
+ 'use strict';
14
+ const getDataType = (obj) => {
15
+ let tmp = Object.prototype.toString.call(obj).slice(8, -1), result;
16
+ if (tmp === 'Function' && /^\s*class\s+/.test(obj.toString())) {
17
+ result = 'Class';
18
+ }
19
+ else if (tmp === 'Object' && Object.getPrototypeOf(obj) !== Object.prototype) {
20
+ result = 'Instance';
21
+ }
22
+ else {
23
+ result = tmp;
24
+ }
25
+ return result;
26
+ //document.createElement -> HTMLxxxElement
27
+ //document.createDocumentFragment() -> DocumentFragment
28
+ //document.createComment() -> Comment
29
+ //document.createTextNode -> Text
30
+ //document.createCDATASection() -> XMLDocument
31
+ //document.createProcessingInstruction() -> ProcessingInstruction
32
+ //document.createRange() -> Range
33
+ //document.createTreeWalker() -> TreeWalker
34
+ //document.createNodeIterator() -> NodeIterator
35
+ //document.createElementNS('http://www.w3.org/2000/svg', 'svg'); -> SVGSVGElement
36
+ //document.createElementNS('http://www.w3.org/1998/Math/MathML', 'math'); -> MathMLElement
37
+ };
38
+ export default getDataType;
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @since Last modified: 2025/12/25 14:22:26
3
+ * @function isEmpty
4
+ * @description Determine whether it is empty data.The data itself is empty data: 0| ''|false|undefined|null; <br>empty function: function () {}|() => {}; <br>empty array and empty objects: []|{}| [null]| [ undefined]| ['']| [""];<br> empty symbol object: symbol()|symbol.For(), will be judged as empty.
5
+ * @param {*} data - Can be any data
6
+ * @returns {boolean} - Return true or false
7
+ * @example
8
+ * ax.isEmpty([null]);
9
+ * <!--return true-->
10
+ */
11
+ //简介:判断是否为空数据。本身为空的数据:0|''|false|undefined|null;空函数:function(){}|()=>{};空数组和空对象:[]|{}|[null]|[undefined]|['']|[""];空Symbol对象:Symbol()|Symbol.for(),都将判断为空。
12
+ //返回:true或false
13
+ 'use strict';
14
+ import getDataType from './getDataType';
15
+ const isEmpty = (data) => {
16
+ let type = getDataType(data), flag;
17
+ if (!data) {
18
+ //0,'',false,undefined,null
19
+ flag = true;
20
+ }
21
+ else {
22
+ //function(){}|()=>{}
23
+ //[null]|[undefined]|['']|[""]
24
+ //[]|{}
25
+ //Symbol()|Symbol.for()
26
+ //Set,Map
27
+ //Date/Regex
28
+ flag = (type === 'Object') ? (Object.keys(data).length === 0) :
29
+ (type === 'Array') ? data.join('') === '' :
30
+ (type === 'Function') ? (data.toString().replace(/\s+/g, '').match(/{.*}/g)[0] === '{}') :
31
+ (type === 'Symbol') ? (data.toString().replace(/\s+/g, '').match(/\(.*\)/g)[0] === '()') :
32
+ (type === 'Set' || type === 'Map') ? data.size === 0 :
33
+ type === 'Date' ? isNaN(data.getTime()) :
34
+ type === 'RegExp' ? data.source === '' :
35
+ type === 'ArrayBuffer' ? data.byteLength === 0 :
36
+ (type === 'NodeList' || type === 'HTMLCollection') ? data.length === 0 :
37
+ ('length' in data && typeof data.length === 'number') ? data.length === 0 :
38
+ ('size' in data && typeof data.size === 'number') ? data.size === 0 :
39
+ (type === 'Error' || data instanceof Error) ? data.message === '' :
40
+ (type.includes('Array') && (['Uint8Array', 'Int8Array', 'Uint16Array', 'Int16Array', 'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array'].includes(type))) ? data.length === 0 :
41
+ false;
42
+ }
43
+ return flag;
44
+ };
45
+ export default isEmpty;
package/src/isEmpty.js ADDED
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @since Last modified: 2025/12/25 14:22:26
3
+ * @function isEmpty
4
+ * @description Determine whether it is empty data.The data itself is empty data: 0| ''|false|undefined|null; <br>empty function: function () {}|() => {}; <br>empty array and empty objects: []|{}| [null]| [ undefined]| ['']| [""];<br> empty symbol object: symbol()|symbol.For(), will be judged as empty.
5
+ * @param {*} data - Can be any data
6
+ * @returns {boolean} - Return true or false
7
+ * @example
8
+ * ax.isEmpty([null]);
9
+ * <!--return true-->
10
+ */
11
+ //简介:判断是否为空数据。本身为空的数据:0|''|false|undefined|null;空函数:function(){}|()=>{};空数组和空对象:[]|{}|[null]|[undefined]|['']|[""];空Symbol对象:Symbol()|Symbol.for(),都将判断为空。
12
+ //返回:true或false
13
+ 'use strict';
14
+ import getDataType from './getDataType';
15
+ const isEmpty = (data) => {
16
+ let type = getDataType(data), flag;
17
+ if (!data) {
18
+ //0,'',false,undefined,null
19
+ flag = true;
20
+ }
21
+ else {
22
+ //function(){}|()=>{}
23
+ //[null]|[undefined]|['']|[""]
24
+ //[]|{}
25
+ //Symbol()|Symbol.for()
26
+ //Set,Map
27
+ //Date/Regex
28
+ flag = (type === 'Object') ? (Object.keys(data).length === 0) :
29
+ (type === 'Array') ? data.join('') === '' :
30
+ (type === 'Function') ? (data.toString().replace(/\s+/g, '').match(/{.*}/g)[0] === '{}') :
31
+ (type === 'Symbol') ? (data.toString().replace(/\s+/g, '').match(/\(.*\)/g)[0] === '()') :
32
+ (type === 'Set' || type === 'Map') ? data.size === 0 :
33
+ type === 'Date' ? isNaN(data.getTime()) :
34
+ type === 'RegExp' ? data.source === '' :
35
+ type === 'ArrayBuffer' ? data.byteLength === 0 :
36
+ (type === 'NodeList' || type === 'HTMLCollection') ? data.length === 0 :
37
+ ('length' in data && typeof data.length === 'number') ? data.length === 0 :
38
+ ('size' in data && typeof data.size === 'number') ? data.size === 0 :
39
+ (type === 'Error' || data instanceof Error) ? data.message === '' :
40
+ (type.includes('Array') && (['Uint8Array', 'Int8Array', 'Uint16Array', 'Int16Array', 'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array'].includes(type))) ? data.length === 0 :
41
+ false;
42
+ }
43
+ return flag;
44
+ };
45
+ export default isEmpty;
package/src/isEmpty.ts ADDED
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @since Last modified: 2025/12/25 14:22:26
3
+ * @function isEmpty
4
+ * @description Determine whether it is empty data.The data itself is empty data: 0| ''|false|undefined|null; <br>empty function: function () {}|() => {}; <br>empty array and empty objects: []|{}| [null]| [ undefined]| ['']| [""];<br> empty symbol object: symbol()|symbol.For(), will be judged as empty.
5
+ * @param {*} data - Can be any data
6
+ * @returns {boolean} - Return true or false
7
+ * @example
8
+ * ax.isEmpty([null]);
9
+ * <!--return true-->
10
+ */
11
+ //简介:判断是否为空数据。本身为空的数据:0|''|false|undefined|null;空函数:function(){}|()=>{};空数组和空对象:[]|{}|[null]|[undefined]|['']|[""];空Symbol对象:Symbol()|Symbol.for(),都将判断为空。
12
+ //返回:true或false
13
+ 'use strict';
14
+ import getDataType from './getDataType';
15
+ const isEmpty = (data: any): boolean => {
16
+ let type = getDataType(data), flag: boolean;
17
+ if (!data) {
18
+ //0,'',false,undefined,null
19
+ flag = true;
20
+ } else {
21
+ //function(){}|()=>{}
22
+ //[null]|[undefined]|['']|[""]
23
+ //[]|{}
24
+ //Symbol()|Symbol.for()
25
+ //Set,Map
26
+ //Date/Regex
27
+ flag = (type === 'Object') ? (Object.keys(data).length === 0) :
28
+ (type === 'Array') ? data.join('') === '' :
29
+ (type === 'Function') ? (data.toString().replace(/\s+/g, '').match(/{.*}/g)[0] === '{}') :
30
+ (type === 'Symbol') ? (data.toString().replace(/\s+/g, '').match(/\(.*\)/g)[0] === '()') :
31
+ (type === 'Set' || type === 'Map') ? data.size === 0 :
32
+ type === 'Date' ? isNaN(data.getTime()) :
33
+ type === 'RegExp' ? data.source === '' :
34
+ type === 'ArrayBuffer' ? data.byteLength === 0 :
35
+ (type === 'NodeList' || type === 'HTMLCollection') ? data.length === 0 :
36
+ ('length' in data && typeof data.length === 'number') ? data.length === 0 :
37
+ ('size' in data && typeof data.size === 'number') ? data.size === 0 :
38
+ (type === 'Error' || data instanceof Error) ? data.message === '' :
39
+ (type.includes('Array') && (['Uint8Array', 'Int8Array', 'Uint16Array', 'Int16Array', 'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array'].includes(type))) ? data.length === 0 :
40
+ false;
41
+ }
42
+ return flag;
43
+ }
44
+ export default isEmpty;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @since Last modified: 2025/12/25 12:07:26
2
+ * @since Last modified: 2025/12/25 14:29:53
3
3
  * shallowCopy
4
4
  *
5
5
  * This function performs a shallow copy of various data structures:
@@ -7,13 +7,21 @@
7
7
  * - Map
8
8
  * - Array
9
9
  * - Plain Object (including properties with Symbol keys)
10
+ * - Date
11
+ * - RegExp
12
+ * - Buffer (Node.js)
13
+ * - ArrayBuffer and Typed Arrays
14
+ * - WeakSet
15
+ * - WeakMap
16
+ * - Error
10
17
  *
11
18
  * It returns a new instance of the data structure, but the elements or properties of reference types (such as objects or arrays) will be copied by reference.
12
19
  * Primitive types (e.g., number, string, boolean) will be returned directly.
13
20
  */
14
21
  'use strict';
22
+ import copyObjectWithSymbol from "./copyObjectWithSymbol";
15
23
  import getDataType from "./getDataType";
16
- const shallowCopy = (data) => {
24
+ const shallowCopy = (data, options = {}) => {
17
25
  const dataType = getDataType(data);
18
26
  // Check if data is a Set
19
27
  if (dataType === 'Set') {
@@ -32,13 +40,37 @@ const shallowCopy = (data) => {
32
40
  }
33
41
  // Check if data is a Plain Object (including Symbol keys)
34
42
  if (dataType === 'object') {
35
- const obj = data; // Ensure the object type includes string and symbol keys
36
- const symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc, sym) => {
37
- acc[sym] = obj[sym];
38
- return acc;
39
- }, {});
43
+ // Ensure the object type includes string and symbol keys
40
44
  // Shallow copy the object and include the Symbol properties
41
- return { ...obj, ...symbolProperties };
45
+ return copyObjectWithSymbol(data);
46
+ }
47
+ // Check if data is a Date
48
+ if (dataType === 'Date') {
49
+ return new Date(data.getTime());
50
+ }
51
+ // Check if data is a RegExp
52
+ if (dataType === 'RegExp') {
53
+ return new RegExp(data.source, data.flags);
54
+ }
55
+ // Check if data is a Buffer (for Node.js)
56
+ if (dataType === 'Buffer') {
57
+ return Buffer.from(data);
58
+ }
59
+ // Check if data is an ArrayBuffer or TypedArray
60
+ if (dataType === 'ArrayBuffer' || ArrayBuffer.isView(data)) {
61
+ return data.slice(0);
62
+ }
63
+ // Check if data is a WeakSet
64
+ if (dataType === 'WeakSet') {
65
+ return new WeakSet([...data]);
66
+ }
67
+ // Check if data is a WeakMap
68
+ if (dataType === 'WeakMap') {
69
+ return new WeakMap([...data]);
70
+ }
71
+ // Check if data is an Error
72
+ if (dataType === 'Error') {
73
+ return new Error(data.message);
42
74
  }
43
75
  // For other types (such as numbers, strings, booleans, etc.), return the original value
44
76
  return data;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @since Last modified: 2025/12/25 12:07:26
2
+ * @since Last modified: 2025/12/25 14:29:53
3
3
  * shallowCopy
4
4
  *
5
5
  * This function performs a shallow copy of various data structures:
@@ -7,15 +7,23 @@
7
7
  * - Map
8
8
  * - Array
9
9
  * - Plain Object (including properties with Symbol keys)
10
+ * - Date
11
+ * - RegExp
12
+ * - Buffer (Node.js)
13
+ * - ArrayBuffer and Typed Arrays
14
+ * - WeakSet
15
+ * - WeakMap
16
+ * - Error
10
17
  *
11
18
  * It returns a new instance of the data structure, but the elements or properties of reference types (such as objects or arrays) will be copied by reference.
12
19
  * Primitive types (e.g., number, string, boolean) will be returned directly.
13
20
  */
14
21
  'use strict';
15
22
 
23
+ import copyObjectWithSymbol from "./copyObjectWithSymbol";
16
24
  import getDataType from "./getDataType";
17
25
 
18
- const shallowCopy = (data: any): any => {
26
+ const shallowCopy = (data: any,options={}): any => {
19
27
  const dataType = getDataType(data);
20
28
 
21
29
  // Check if data is a Set
@@ -38,14 +46,44 @@ const shallowCopy = (data: any): any => {
38
46
 
39
47
  // Check if data is a Plain Object (including Symbol keys)
40
48
  if (dataType === 'object') {
41
- const obj = data as { [key: string | symbol]: any }; // Ensure the object type includes string and symbol keys
42
- const symbolProperties = Object.getOwnPropertySymbols(obj).reduce((acc: { [key: symbol]: any }, sym: symbol) => {
43
- acc[sym] = obj[sym];
44
- return acc;
45
- }, {});
46
-
49
+ // Ensure the object type includes string and symbol keys
47
50
  // Shallow copy the object and include the Symbol properties
48
- return { ...obj, ...symbolProperties };
51
+ return copyObjectWithSymbol(data);
52
+ }
53
+
54
+ // Check if data is a Date
55
+ if (dataType === 'Date') {
56
+ return new Date(data.getTime());
57
+ }
58
+
59
+ // Check if data is a RegExp
60
+ if (dataType === 'RegExp') {
61
+ return new RegExp(data.source, data.flags);
62
+ }
63
+
64
+ // Check if data is a Buffer (for Node.js)
65
+ if (dataType === 'Buffer') {
66
+ return Buffer.from(data);
67
+ }
68
+
69
+ // Check if data is an ArrayBuffer or TypedArray
70
+ if (dataType === 'ArrayBuffer' || ArrayBuffer.isView(data)) {
71
+ return data.slice(0);
72
+ }
73
+
74
+ // Check if data is a WeakSet
75
+ if (dataType === 'WeakSet') {
76
+ return new WeakSet([...data]);
77
+ }
78
+
79
+ // Check if data is a WeakMap
80
+ if (dataType === 'WeakMap') {
81
+ return new WeakMap([...data]);
82
+ }
83
+
84
+ // Check if data is an Error
85
+ if (dataType === 'Error') {
86
+ return new Error(data.message);
49
87
  }
50
88
 
51
89
  // For other types (such as numbers, strings, booleans, etc.), return the original value