@codady/utils 0.0.11 → 0.0.13
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 +40 -2
- package/dist/utils.cjs.js +269 -213
- package/dist/utils.cjs.min.js +3 -3
- package/dist/utils.esm.js +269 -213
- package/dist/utils.esm.min.js +3 -3
- package/dist/utils.umd.js +273 -215
- package/dist/utils.umd.min.js +3 -3
- package/dist.zip +0 -0
- package/examples/deepMerge.html +1049 -0
- package/modules.js +5 -11
- package/modules.ts +7 -7
- package/package.json +1 -1
- package/src/copyObjectWithSymbol.js +26 -0
- package/src/copyObjectWithSymbol.ts +28 -0
- package/src/deepEqual.js +1 -1
- package/src/deepEqual.ts +1 -1
- package/src/deepMerge.js +253 -13
- package/src/deepMerge.ts +306 -18
- package/src/deepMergeHelper.js +1 -3
- package/src/deepMergeHelper.ts +1 -3
- package/src/deepMergeMaps.js +4 -4
- package/src/deepMergeMaps.ts +6 -6
- package/src/deepMergeObjects.js +11 -4
- package/src/deepMergeObjects.ts +10 -4
- package/src/deepMergeSets.js +5 -10
- package/src/deepMergeSets.ts +6 -9
- package/src/getDataType - /345/211/257/346/234/254.js" +38 -0
- package/src/isEmpty - /345/211/257/346/234/254.js" +45 -0
- package/src/isEmpty.js +45 -0
- package/src/isEmpty.ts +44 -0
- package/src/mapMutableMethods - /345/211/257/346/234/254.js" +5 -0
- package/src/shallowCopy.js +78 -0
- package/src/shallowCopy.ts +93 -0
package/src/deepMerge.ts
CHANGED
|
@@ -1,40 +1,328 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 12:10:30
|
|
3
3
|
* @function deepMerge
|
|
4
4
|
* @description Deeply merges two data structures (Object, Array, Map, or Set) based on their types.
|
|
5
5
|
* This function recursively merges the properties or items of the target and source, depending on their types.
|
|
6
6
|
* If the types of target and source do not match, the target will be returned unchanged.
|
|
7
|
+
* 深度合并两个数据结构(对象、数组、Map或Set),根据类型递归合并属性和项。
|
|
8
|
+
* 如果目标和源的类型不匹配,则目标保持不变。
|
|
7
9
|
* @param target The target data structure to merge into (can be Object, Array, Map, or Set).
|
|
10
|
+
* 要合并到的目标数据结构(可以是对象、数组、Map或Set)。
|
|
8
11
|
* @param source The source data structure to merge from (can be Object, Array, Map, or Set).
|
|
12
|
+
* 要合并的源数据结构(可以是对象、数组、Map或Set)。
|
|
9
13
|
* @param opts Configuration options for merging. The default options include:
|
|
10
|
-
*
|
|
11
|
-
* - `
|
|
14
|
+
* 合并的配置选项,默认值包括:
|
|
15
|
+
* - `dataMode`: Specifies the merging mode (`'clear'`, `'replace'`, or `'concat'`).
|
|
16
|
+
* 指定合并模式('clear'、'replace' 或 'concat')。
|
|
17
|
+
* - `inheritMissing`: Whether to append properties from the source if they do not exist in the target.
|
|
18
|
+
* 如果源中的属性在目标中不存在,是否追加这些属性。
|
|
12
19
|
* - `targetClone`: Whether to clone the target before merging (if true, the target is not modified).
|
|
20
|
+
* 是否在合并前克隆目标对象(如果为true,则目标对象不会被修改)。
|
|
13
21
|
* - `useEnable`: Some special handling for specific objects that have `enable` properties.
|
|
22
|
+
* 对具有enable属性的特定对象进行特殊处理。
|
|
14
23
|
* - `useSymbol`: Whether to merge symbol properties.
|
|
24
|
+
* 是否合并symbol属性。
|
|
15
25
|
* @returns The deeply merged target data structure.
|
|
26
|
+
* 深度合并后的目标数据结构。
|
|
16
27
|
* @example
|
|
17
28
|
* let x = { a: 'man', b: 0, c: [] };
|
|
18
29
|
* let y = { a: 'woman', b: 2, d: 'new' };
|
|
19
|
-
* const merged = deepMerge(x, y, {
|
|
30
|
+
* const merged = deepMerge(x, y, { dataMode: 'clear', inheritMissing: true });
|
|
20
31
|
* // Returns { a: 'woman', b: 2, c: [], d: 'new' }
|
|
32
|
+
* // 返回 { a: 'woman', b: 2, c: [], d: 'new' }
|
|
21
33
|
*/
|
|
22
34
|
'use strict';
|
|
23
35
|
import getDataType from './getDataType';
|
|
24
|
-
import
|
|
25
|
-
import
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
36
|
+
import deepClone from './deepClone';
|
|
37
|
+
import shallowCopy from './shallowCopy';
|
|
38
|
+
|
|
39
|
+
// Define options for deep merging
|
|
40
|
+
// 定义深度合并的选项
|
|
41
|
+
export interface DeepMergeOptions {
|
|
42
|
+
// Mode for handling array items
|
|
43
|
+
// 处理数组成员的模式
|
|
44
|
+
dataMode?: 'clear' | 'replace' | 'concat';
|
|
45
|
+
// Whether to append properties (for objects)
|
|
46
|
+
// 是否追加属性(针对对象)
|
|
47
|
+
inheritMissing?: boolean;
|
|
48
|
+
// Whether to clone the target
|
|
49
|
+
// 是否克隆目标对象
|
|
50
|
+
targetClone?: boolean;
|
|
51
|
+
// If target={enable:true}, source=false, then output target={enable:false}
|
|
52
|
+
// 如果target={enable:true},source=false,那么输出target={enable:false}
|
|
53
|
+
useEnable?: boolean;
|
|
54
|
+
// Whether to process keys of symbol type when merging objects
|
|
55
|
+
// 合并对象时是否处理symbol类型的键
|
|
56
|
+
useSymbol?: boolean;
|
|
57
|
+
|
|
58
|
+
// Options passed to the deepClone function when cloning is enabled
|
|
59
|
+
// 启用克隆时传递给deepClone函数的选项
|
|
60
|
+
deepClone?: Record<string, any>;
|
|
61
|
+
|
|
62
|
+
// Callback function executed before merging each data structure
|
|
63
|
+
// 在每个数据结构合并前执行的回调函数
|
|
64
|
+
onBeforeMerge?: (
|
|
65
|
+
target: Object | Array<any> | Map<any, any> | Set<any>,
|
|
66
|
+
source: Object | Array<any> | Map<any, any> | Set<any> | any
|
|
67
|
+
) => void;
|
|
68
|
+
|
|
69
|
+
// Callback function executed after merging each data structure
|
|
70
|
+
// 在每个数据结构合并后执行的回调函数
|
|
71
|
+
onAfterMerge?: (
|
|
72
|
+
result: Object | Array<any> | Map<any, any> | Set<any>,
|
|
73
|
+
originalTarget: Object | Array<any> | Map<any, any> | Set<any>,
|
|
74
|
+
source: Object | Array<any> | Map<any, any> | Set<any> | any
|
|
75
|
+
) => void;
|
|
76
|
+
}
|
|
77
|
+
export type EnableObject = {
|
|
78
|
+
enable: boolean;
|
|
79
|
+
[key: string]: any;
|
|
80
|
+
[key: symbol]: any;
|
|
81
|
+
};
|
|
82
|
+
|
|
29
83
|
const deepMerge = (target: Object | Array<any> | Map<any, any> | Set<any>, source: any, opts: DeepMergeOptions = {}): Object | Array<any> | Map<any, any> | Set<any> => {
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
84
|
+
// Set default options
|
|
85
|
+
// 设置默认选项
|
|
86
|
+
const options = Object.assign({
|
|
87
|
+
// Merging mode for array and set collections:
|
|
88
|
+
// 'clear' means clear first then append; 'concat' means append directly at the end;
|
|
89
|
+
// 'replace' means merge sequentially (deep merging)
|
|
90
|
+
// 对于array和set合集的合并方式:'clear'表示先清空再追加;'concat'表示直接在尾部追加;
|
|
91
|
+
// 'replace'表示按顺序进行合并(深度合并)
|
|
92
|
+
dataMode: 'clear',
|
|
93
|
+
|
|
94
|
+
// Whether to directly append properties/items from source that target doesn't have.
|
|
95
|
+
// true: append; false: discard
|
|
96
|
+
// source对象如果有target对象没有的item或prop属性,是否直接新追加。true则追加;false则丢弃
|
|
97
|
+
inheritMissing: true,
|
|
98
|
+
|
|
99
|
+
// Whether to clone the target object, generating a brand new object. Default false.
|
|
100
|
+
// 是否克隆target对象,生成全新对象,默认false。
|
|
101
|
+
targetClone: false,
|
|
102
|
+
|
|
103
|
+
// How to merge when target or source has enable property and boolean value into {enable:boolean}
|
|
104
|
+
// 当target或source有enable属性(prop)和boolean值时,如何合并为{enable:boolean}
|
|
105
|
+
useEnable: true,
|
|
106
|
+
|
|
107
|
+
// Whether to allow merging key=symbol key-value pairs when target is {} type.
|
|
108
|
+
// target是{}类型时,是否允许合并key=symbol的键值对。
|
|
109
|
+
useSymbol: true,
|
|
110
|
+
|
|
111
|
+
// Options passed to the deepClone function when targetClone is true
|
|
112
|
+
// 当targetClone为true时传递给deepClone函数的选项
|
|
113
|
+
deepClone: {},
|
|
114
|
+
|
|
115
|
+
// Callback function executed before merging each data structure
|
|
116
|
+
// 在每个数据结构合并前执行的回调函数
|
|
117
|
+
onBeforeMerge: undefined,
|
|
118
|
+
|
|
119
|
+
// Callback function executed after merging each data structure
|
|
120
|
+
// 在每个数据结构合并后执行的回调函数
|
|
121
|
+
onAfterMerge: undefined,
|
|
122
|
+
}, opts),
|
|
123
|
+
// Main helper function for recursive merging
|
|
124
|
+
// 递归合并的主辅助函数
|
|
125
|
+
deepMergeHelper = (target: any, source: any, options: DeepMergeOptions): any => {
|
|
126
|
+
let targetType = getDataType(target),
|
|
127
|
+
sourceType = getDataType(source),
|
|
128
|
+
flag = true,
|
|
129
|
+
type,
|
|
130
|
+
result;
|
|
131
|
+
// Determine the type and perform appropriate merging
|
|
132
|
+
// 确定类型并执行相应的合并
|
|
133
|
+
if (targetType === 'Object' && sourceType === 'Object') {
|
|
134
|
+
result = deepMergeObjects(target, source, options);
|
|
135
|
+
type = 'Object';
|
|
136
|
+
} else if (targetType === 'Array' && sourceType === 'Array') {
|
|
137
|
+
result = deepMergeArrays(target, source, options);
|
|
138
|
+
type = 'Array';
|
|
139
|
+
} else if (targetType === 'Set' && sourceType === 'Set') {
|
|
140
|
+
result = deepMergeSets(target, source, options);
|
|
141
|
+
type = 'Set';
|
|
142
|
+
} else if (targetType === 'Map' && sourceType === 'Map') {
|
|
143
|
+
result = deepMergeMaps(target, source, options);
|
|
144
|
+
type = 'Map';
|
|
145
|
+
} else {
|
|
146
|
+
flag = false;
|
|
147
|
+
result = target;
|
|
148
|
+
}
|
|
149
|
+
return { result, flag, type };
|
|
150
|
+
},
|
|
151
|
+
// Special handling for objects with enable property
|
|
152
|
+
// 对具有enable属性的对象进行特殊处理
|
|
153
|
+
mergeEnableObject = (target: EnableObject | boolean, source: EnableObject | boolean) => {
|
|
154
|
+
if (target?.hasOwnProperty('enable') && typeof source === 'boolean') {
|
|
155
|
+
//result={enable:true,a:'',b:''},source[k]=false=>result={enable:false,a:'',b:''}
|
|
156
|
+
//仅设置enable属性
|
|
157
|
+
(target as EnableObject).enable = source;
|
|
158
|
+
//返回target原对象
|
|
159
|
+
return target;
|
|
160
|
+
} else if (source?.hasOwnProperty('enable') && typeof target === 'boolean') {
|
|
161
|
+
//source={enable:true,a:'',b:''},(result as any)[k]=false=>result={enable:false,a:'',b:''}
|
|
162
|
+
//返回新值,新值包含enable属性
|
|
163
|
+
return Object.assign({ enable: target }, source);
|
|
164
|
+
}
|
|
165
|
+
return source;
|
|
166
|
+
},
|
|
167
|
+
// Deep merge for objects
|
|
168
|
+
// 对象的深度合并
|
|
169
|
+
deepMergeObjects = (target: Object, source: any, opts: DeepMergeOptions = {}): Object => {
|
|
170
|
+
let targetType = getDataType(target),
|
|
171
|
+
sourceType = getDataType(source);
|
|
172
|
+
// If target is not an object or source is empty, return target directly
|
|
173
|
+
// 如果target不是对象或者source为空则直接返回
|
|
174
|
+
if (targetType !== 'Object' || sourceType !== 'Object') {
|
|
175
|
+
return target;
|
|
176
|
+
}
|
|
177
|
+
opts?.onBeforeMerge?.(target, source);
|
|
178
|
+
|
|
179
|
+
const options = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, opts);
|
|
180
|
+
let result: any = {};
|
|
181
|
+
// If cloning is enabled, clone the target first
|
|
182
|
+
// 如果是复制方法,则先复制target
|
|
183
|
+
result = options.targetClone ? shallowCopy(target) : target;
|
|
184
|
+
|
|
185
|
+
for (let k in source) {
|
|
186
|
+
if (source.hasOwnProperty(k) && result.hasOwnProperty(k)) {
|
|
187
|
+
|
|
188
|
+
let resp = deepMergeHelper((result as any)[k], source[k], opts);
|
|
189
|
+
//resp={result,flag,type}
|
|
190
|
+
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
191
|
+
if (!resp.flag) {
|
|
192
|
+
//类型不同则直接覆盖
|
|
193
|
+
if (options.useEnable) {
|
|
194
|
+
(result as any)[k] = mergeEnableObject((result as any)[k], source[k]);
|
|
195
|
+
} else {
|
|
196
|
+
//完全替换
|
|
197
|
+
(result as any)[k] = source[k];
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
//类型相同
|
|
201
|
+
if (resp.type) {
|
|
202
|
+
if (resp.type === 'Object') {
|
|
203
|
+
//如果遇上对象则深度复制
|
|
204
|
+
(result as any)[k] = resp.result;
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
//其他类型则直接覆盖
|
|
208
|
+
(result as any)[k] = source[k];
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
} else if (source.hasOwnProperty(k) && !result.hasOwnProperty(k) && options.inheritMissing) {
|
|
213
|
+
//如果source有属性,result没有该属性,但是options允许追加属性则直接赋值
|
|
214
|
+
(result as any)[k] = source[k];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
//Symbol键直接追加,因为Symbol是唯一,结果同Object.assign
|
|
218
|
+
if (options.useSymbol) {
|
|
219
|
+
let symbols = Object.getOwnPropertySymbols(source);
|
|
220
|
+
if (symbols.length) {
|
|
221
|
+
for (let k of symbols) (result as any)[k] = source[k];
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
options?.onAfterMerge?.(result, target, source);
|
|
225
|
+
return result;
|
|
226
|
+
},
|
|
227
|
+
deepMergeArrays = (target: any[], source: any[], options: DeepMergeOptions = {}): any[] => {
|
|
228
|
+
// Ensure both target and source are arrays
|
|
229
|
+
if (!Array.isArray(target) || !Array.isArray(source)) return target;
|
|
230
|
+
options?.onBeforeMerge?.(target, source);
|
|
231
|
+
// Merge options, with default values
|
|
232
|
+
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false }, options),
|
|
233
|
+
|
|
234
|
+
// If cloning is enabled, create a deep copy of the target array
|
|
235
|
+
result = opts.targetClone ? [...target] : target;
|
|
236
|
+
|
|
237
|
+
// Handle different merge strategies based on dataMode
|
|
238
|
+
if (opts.dataMode === 'replace') {
|
|
239
|
+
// "replace" mode: recursively merge items in the arrays
|
|
240
|
+
for (let i = 0; i < source.length; i++) {
|
|
241
|
+
// If not allowed to add beyond length
|
|
242
|
+
// 如果不允许添加超过长度
|
|
243
|
+
if (!opts.inheritMissing && i >= result.length) break;
|
|
244
|
+
let resp = deepMergeHelper(result[i], source[i], opts);
|
|
245
|
+
//resp={result,flag,type}
|
|
246
|
+
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
247
|
+
if (!resp.flag) {
|
|
248
|
+
result[i] = source[i];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
} else if (opts.dataMode === 'concat') {
|
|
252
|
+
// Concatenate mode: append all items from the source array to the target array
|
|
253
|
+
result.push(...source);
|
|
254
|
+
} else {
|
|
255
|
+
//Default replace mode: clear the target array and push all items from the source array
|
|
256
|
+
result.length = 0;
|
|
257
|
+
result.push(...source);
|
|
258
|
+
}
|
|
259
|
+
options?.onAfterMerge?.(result, target, source);
|
|
260
|
+
return result;
|
|
261
|
+
},
|
|
262
|
+
deepMergeMaps = (target: Map<any, any>, source: Map<any, any>, options: DeepMergeOptions = {}): Map<any, any> => {
|
|
263
|
+
// Ensure both target and source are Maps
|
|
264
|
+
if (!(target instanceof Map) || !(source instanceof Map)) return target;
|
|
265
|
+
options?.onBeforeMerge?.(target, source);
|
|
266
|
+
// Merge options, with default values
|
|
267
|
+
const opts = Object.assign({ inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
268
|
+
|
|
269
|
+
// If cloning is enabled, create a deep copy of the target Map
|
|
270
|
+
result = opts.targetClone ? new Map([...target]) : target;
|
|
271
|
+
|
|
272
|
+
// Default "merge" mode: recursively merge entries in the Maps
|
|
273
|
+
for (const [key, value] of source.entries())
|
|
274
|
+
// Check if the key already exists in the target Map
|
|
275
|
+
if (result.has(key)) {
|
|
276
|
+
const _target = result.get(key),
|
|
277
|
+
_source = value,
|
|
278
|
+
resp = deepMergeHelper(_target, _source, opts);
|
|
279
|
+
//resp={result,flag,type}
|
|
280
|
+
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
281
|
+
if (!resp.flag) {
|
|
282
|
+
// For simple values, overwrite the target value with the source value
|
|
283
|
+
result.set(key, _source);
|
|
284
|
+
} else {
|
|
285
|
+
// If both target and source are objects, merge them recursively
|
|
286
|
+
resp.type === 'Object' && result.set(key, resp.result);
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
// If the key doesn't exist in the target, add the entry from the source Map
|
|
290
|
+
options.inheritMissing && result.set(key, value);
|
|
291
|
+
}
|
|
292
|
+
options?.onAfterMerge?.(result, target, source);
|
|
293
|
+
return result;
|
|
294
|
+
},
|
|
295
|
+
deepMergeSets = (target: Set<any>, source: Set<any>, options: DeepMergeOptions = {}): Set<any> => {
|
|
296
|
+
// Ensure both target and source are Sets
|
|
297
|
+
if (!(target instanceof Set) || !(source instanceof Set)) return target;
|
|
298
|
+
options?.onBeforeMerge?.(target, source);
|
|
299
|
+
// Merge options, with default values
|
|
300
|
+
const opts = Object.assign({ dataMode: 'clear', inheritMissing: true, targetClone: false, useEnable: true }, options),
|
|
301
|
+
|
|
302
|
+
// If cloning is enabled, create a deep copy of the target Set
|
|
303
|
+
result = opts.targetClone ? new Set(...target) : target;
|
|
304
|
+
|
|
305
|
+
// Handle different merge strategies based on dataMode
|
|
306
|
+
if (opts.dataMode === 'replace') {
|
|
307
|
+
// Replace mode: recursively merge items in the Sets
|
|
308
|
+
const _result = [...result],
|
|
309
|
+
_source = [...source],
|
|
310
|
+
resp = deepMergeHelper(_result, _source, opts);
|
|
311
|
+
result.clear();
|
|
312
|
+
for (let item of resp.result) result.add(item);
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
} else if (opts.dataMode === 'concat') {
|
|
316
|
+
// Concatenate mode: add all items from the source Set to the target Set
|
|
317
|
+
for (let item of source) result.add(item);
|
|
318
|
+
} else {
|
|
319
|
+
//Default "clear" mode: clear the target Set and add all items from the source Set
|
|
320
|
+
result.clear();
|
|
321
|
+
for (let item of source) result.add(item);
|
|
322
|
+
}
|
|
323
|
+
options?.onAfterMerge?.(result, target, source);
|
|
324
|
+
return result;
|
|
325
|
+
};
|
|
326
|
+
return deepMergeHelper(target, source, options).result;
|
|
39
327
|
}
|
|
40
328
|
export default deepMerge;
|
package/src/deepMergeHelper.js
CHANGED
package/src/deepMergeHelper.ts
CHANGED
|
@@ -37,9 +37,7 @@ const deepMergeHelper = (target: any, source: any, options: DeepMergeOptions): a
|
|
|
37
37
|
flag = false;
|
|
38
38
|
result = target; // Default case, replace primitive values
|
|
39
39
|
}
|
|
40
|
-
return {
|
|
41
|
-
result, flag,type
|
|
42
|
-
};
|
|
40
|
+
return { result, flag,type};
|
|
43
41
|
}
|
|
44
42
|
|
|
45
43
|
export default deepMergeHelper;
|
package/src/deepMergeMaps.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 08:22:06
|
|
3
3
|
* @function deepMergeMaps
|
|
4
4
|
* Deeply merges two Maps, with flexible options to replace, concatenate, or merge entries.
|
|
5
5
|
* @param target The target Map to merge into
|
|
@@ -34,12 +34,12 @@ const deepMergeMaps = (target, source, options = { itemMode: 'merge', propAppend
|
|
|
34
34
|
source.forEach((value, key) => {
|
|
35
35
|
// Check if the key already exists in the target Map
|
|
36
36
|
if (result.has(key)) {
|
|
37
|
-
const
|
|
37
|
+
const _target = result.get(key), _source = value, resp = deepMergeHelper(_target, _source, opts);
|
|
38
38
|
//resp={result,flag,type}
|
|
39
39
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
40
40
|
if (!resp.flag) {
|
|
41
41
|
// For simple values, overwrite the target value with the source value
|
|
42
|
-
result.set(key,
|
|
42
|
+
result.set(key, _source);
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
45
|
// If both target and source are objects, merge them recursively
|
|
@@ -48,7 +48,7 @@ const deepMergeMaps = (target, source, options = { itemMode: 'merge', propAppend
|
|
|
48
48
|
}
|
|
49
49
|
else {
|
|
50
50
|
// If the key doesn't exist in the target, add the entry from the source Map
|
|
51
|
-
result.set(key, value);
|
|
51
|
+
options.propAppend && result.set(key, value);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
54
|
return result;
|
package/src/deepMergeMaps.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 08:22:06
|
|
3
3
|
* @function deepMergeMaps
|
|
4
4
|
* Deeply merges two Maps, with flexible options to replace, concatenate, or merge entries.
|
|
5
5
|
* @param target The target Map to merge into
|
|
@@ -42,21 +42,21 @@ const deepMergeMaps = (target: Map<any, any>, source: Map<any, any>, options: De
|
|
|
42
42
|
source.forEach((value, key) => {
|
|
43
43
|
// Check if the key already exists in the target Map
|
|
44
44
|
if (result.has(key)) {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
resp = deepMergeHelper(
|
|
45
|
+
const _target = result.get(key),
|
|
46
|
+
_source = value,
|
|
47
|
+
resp = deepMergeHelper(_target, _source, opts);
|
|
48
48
|
//resp={result,flag,type}
|
|
49
49
|
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
50
50
|
if (!resp.flag) {
|
|
51
51
|
// For simple values, overwrite the target value with the source value
|
|
52
|
-
result.set(key,
|
|
52
|
+
result.set(key, _source);
|
|
53
53
|
} else {
|
|
54
54
|
// If both target and source are objects, merge them recursively
|
|
55
55
|
resp.type === 'Object' && result.set(key, resp.result);
|
|
56
56
|
}
|
|
57
57
|
} else {
|
|
58
58
|
// If the key doesn't exist in the target, add the entry from the source Map
|
|
59
|
-
result.set(key, value);
|
|
59
|
+
options.propAppend && result.set(key, value);
|
|
60
60
|
}
|
|
61
61
|
});
|
|
62
62
|
|
package/src/deepMergeObjects.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 08:21:18
|
|
3
3
|
* @function deepMergeObjects
|
|
4
4
|
* @description Merge two objects. The key name of Source is allowed to be the Symbol type, and the Symbol key name of the source will be added directly to the target.
|
|
5
5
|
* @param {Object} target - The original target of the merge.
|
|
@@ -57,9 +57,16 @@ const deepMergeObjects = (target, source, opts = {}) => {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
else {
|
|
60
|
-
|
|
61
|
-
if (resp.type
|
|
62
|
-
|
|
60
|
+
//类型相同
|
|
61
|
+
if (resp.type) {
|
|
62
|
+
if (resp.type === 'Object') {
|
|
63
|
+
//如果遇上对象则深度复制
|
|
64
|
+
result[k] = resp.result;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
//其他清空则直接覆盖
|
|
69
|
+
result[k] = source[k];
|
|
63
70
|
}
|
|
64
71
|
}
|
|
65
72
|
}
|
package/src/deepMergeObjects.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 08:21:18
|
|
3
3
|
* @function deepMergeObjects
|
|
4
4
|
* @description Merge two objects. The key name of Source is allowed to be the Symbol type, and the Symbol key name of the source will be added directly to the target.
|
|
5
5
|
* @param {Object} target - The original target of the merge.
|
|
@@ -60,9 +60,15 @@ const deepMergeObjects = (target: Object, source: any, opts: DeepMergeOptions =
|
|
|
60
60
|
(result as any)[k] = source[k];
|
|
61
61
|
}
|
|
62
62
|
} else {
|
|
63
|
-
|
|
64
|
-
if (resp.type
|
|
65
|
-
(
|
|
63
|
+
//类型相同
|
|
64
|
+
if (resp.type) {
|
|
65
|
+
if (resp.type === 'Object') {
|
|
66
|
+
//如果遇上对象则深度复制
|
|
67
|
+
(result as any)[k] = resp.result;
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
//其他清空则直接覆盖
|
|
71
|
+
(result as any)[k] = source[k];
|
|
66
72
|
}
|
|
67
73
|
}
|
|
68
74
|
|
package/src/deepMergeSets.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 08:10:14
|
|
3
3
|
* @function deepMergeSets
|
|
4
4
|
* Deeply merges two Sets, with flexible options to replace, concatenate, or merge items.
|
|
5
5
|
* @param target The target Set to merge into
|
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
* @returns The deeply merged Set
|
|
9
9
|
*/
|
|
10
10
|
'use strict';
|
|
11
|
-
import deepEqual from './deepEqual';
|
|
12
11
|
import deepMergeHelper from './deepMergeHelper';
|
|
13
12
|
const deepMergeSets = (target, source, options = { itemMode: 'merge', propAppend: true, targetClone: false, useEnable: true }) => {
|
|
14
13
|
// Ensure both target and source are Sets
|
|
@@ -34,14 +33,10 @@ const deepMergeSets = (target, source, options = { itemMode: 'merge', propAppend
|
|
|
34
33
|
}
|
|
35
34
|
else {
|
|
36
35
|
// Default "merge" mode: recursively merge items in the Sets
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
42
|
-
!resp.flag && result.add(item);
|
|
43
|
-
}
|
|
44
|
-
;
|
|
36
|
+
const _result = [...result], _source = [...source], resp = deepMergeHelper(_result, _source, opts);
|
|
37
|
+
result.clear();
|
|
38
|
+
for (let item of resp.result)
|
|
39
|
+
result.add(item);
|
|
45
40
|
return result;
|
|
46
41
|
}
|
|
47
42
|
};
|
package/src/deepMergeSets.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @since Last modified: 2025/12/
|
|
2
|
+
* @since Last modified: 2025/12/25 08:10:14
|
|
3
3
|
* @function deepMergeSets
|
|
4
4
|
* Deeply merges two Sets, with flexible options to replace, concatenate, or merge items.
|
|
5
5
|
* @param target The target Set to merge into
|
|
@@ -40,14 +40,11 @@ const deepMergeSets = (target: Set<any>, source: Set<any>, options: DeepMergeOpt
|
|
|
40
40
|
return result;
|
|
41
41
|
} else {
|
|
42
42
|
// Default "merge" mode: recursively merge items in the Sets
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
//flag=true表示类型一致并完成了合并,false表示并没有合并需要直接赋值
|
|
49
|
-
!resp.flag && result.add(item);
|
|
50
|
-
};
|
|
43
|
+
const _result = [...result],
|
|
44
|
+
_source = [...source],
|
|
45
|
+
resp = deepMergeHelper(_result, _source, opts);
|
|
46
|
+
result.clear();
|
|
47
|
+
for (let item of resp.result) result.add(item);
|
|
51
48
|
return result;
|
|
52
49
|
}
|
|
53
50
|
}
|
|
@@ -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;
|