yfx
2026-03-17 41d2fe31c18c0a82e0239035c2e50f10fa46c715
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
import $test from './test';
 
/**
 * @description 去除空格
 */
export function trim(
  str: string | number,
  pos: 'both' | 'left' | 'right' | 'all' = 'both',
): string {
  str = String(str);
  if (pos == 'both') {
    return str.replace(/^\s+|\s+$/g, '');
  }
  if (pos == 'left') {
    return str.replace(/^\s*/, '');
  }
  if (pos == 'right') {
    return str.replace(/(\s*$)/g, '');
  }
  if (pos == 'all') {
    return str.replace(/\s+/g, '');
  }
  return str;
}
 
/**
 * 内部递归克隆函数
 * @param obj 要克隆的对象
 * @param visited 已访问对象的映射,用于处理循环引用
 */
function cloneRecursive<T>(obj: T, visited: WeakMap<any, any>): T {
  if (obj === null || obj === undefined) {
    return obj;
  }
 
  if (typeof obj !== 'object') {
    return obj;
  }
 
  // 检查循环引用
  if (visited.has(obj as any)) {
    return visited.get(obj as any);
  }
 
  let cloned: any;
 
  if (obj instanceof Date) {
    cloned = new Date(obj.getTime());
    visited.set(obj as any, cloned);
  } else if (obj instanceof RegExp) {
    cloned = new RegExp(obj.source, obj.flags);
    visited.set(obj as any, cloned);
  } else if ($test.array(obj)) {
    cloned = [];
    visited.set(obj as any, cloned);
    const arr = obj as any;
    for (let i = 0; i < arr.length; i++) {
      cloned[i] = cloneRecursive(arr[i], visited);
    }
  } else if ($test.object(obj)) {
    cloned = {};
    visited.set(obj as any, cloned);
    for (const key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        cloned[key] = cloneRecursive((obj as any)[key], visited);
      }
    }
  } else {
    return obj;
  }
 
  return cloned as T;
}
 
/**
 * @description 深度克隆对象
 * @param {T} obj 需要深度克隆的值,可以是任何类型
 * @returns {T} 克隆后的对象或者原值(原始类型)
 *
 * @example
 * const original = { a: 1, b: { c: 2 }, d: [1, 2, 3] };
 * const cloned = deepClone(original);
 * cloned.b.c = 999;
 * console.log(original.b.c); // 2 (原对象未被修改)
 *
 * @example
 * // 处理循环引用
 * const obj: any = { a: 1 };
 * obj.self = obj;
 * const cloned = deepClone(obj); // 不会无限递归
 */
export function deepClone<T>(obj: T): T {
  return cloneRecursive(obj, new WeakMap());
}
 
/**
 * @description JS对象深度合并
 * @param {Record<string, any>} target 目标对象,默认为空对象
 * @param {Record<string, any>} source 源对象,默认为空对象
 * @returns {T | false} 合并后的对象,如果输入参数无效则返回 false
 *
 * @example
 * const target = { a: 1, b: { c: 2 } };
 * const source = { b: { d: 3 }, e: 4 };
 * const result = deepMerge(target, source);
 * // result: { a: 1, b: { c: 2, d: 3 }, e: 4 }
 *
 * @example
 * // 数组合并
 * const target = { arr: [1, 2] };
 * const source = { arr: [3, 4] };
 * const result = deepMerge(target, source);
 * // result: { arr: [1, 2, 3, 4] }
 */
export function deepMerge<T extends Record<string, any>>(
  target: Record<string, any> = {},
  source: Record<string, any> = {},
): T | false {
  // 检查输入参数的有效性,确保都是普通对象
  if (!$test.object(target) || !$test.object(source)) {
    return false;
  }
 
  // 深克隆目标对象,避免修改原对象
  const result = deepClone(target);
 
  // 遍历源对象的所有可枚举属性
  for (const key in source) {
    // 使用安全的属性检查方法
    if (!Object.prototype.hasOwnProperty.call(source, key)) {
      continue;
    }
 
    const sourceValue = source[key];
    const targetValue = result[key];
 
    // 如果源值和目标值都是数组,则合并数组
    if ($test.array(sourceValue) && $test.array(targetValue)) {
      result[key] = [...targetValue, ...sourceValue];
    }
    // 如果源值和目标值都是对象,则递归合并
    else if ($test.object(sourceValue) && $test.object(targetValue)) {
      const mergedValue = deepMerge(targetValue, sourceValue);
      // 处理递归调用可能返回 false 的情况
      if (mergedValue === false) {
        result[key] = deepClone(sourceValue);
      } else {
        result[key] = mergedValue;
      }
    }
    // 其他情况直接覆盖,并深克隆以避免引用问题
    else {
      result[key] = deepClone(sourceValue);
    }
  }
 
  return result as T;
}