object.assign本身只做浅拷贝,无法直接深合并;但可通过递归判断纯对象并调用自身来模拟深合并,即嵌套对象不覆盖而递归合并,非对象属性则直接覆盖。

Object.assign 本身只做浅拷贝,无法直接实现深合并,但可以通过递归 + Object.assign 模拟出“深合并”的行为——即当目标对象和源对象的某个属性都是普通对象时,不直接覆盖,而是递归合并其内部属性。
核心思路:递归处理嵌套对象
判断当前要合并的属性值是否为纯对象(非 null、typeof 为 'object'、且不是 Array 或 Date 等特殊对象),如果是,则递归调用合并函数;否则直接用 Object.assign 覆盖。
注意:需避免循环引用,简单场景可忽略,生产环境建议加引用检测。
基础深合并函数示例
以下是一个轻量、可读性强的实现:
function deepAssign(target, ...sources) {
if (!target || typeof target !== 'object') return target;
sources.forEach(source => {
if (!source || typeof source !== 'object') return;
Object.keys(source).forEach(key => {
const targetVal = target[key];
const sourceVal = source[key];
if (
sourceVal &&
typeof sourceVal === 'object' &&
!Array.isArray(sourceVal) &&
!(sourceVal instanceof Date)
) {
if (targetVal && typeof targetVal === 'object' && !Array.isArray(targetVal)) {
deepAssign(targetVal, sourceVal);
} else {
target[key] = Array.isArray(sourceVal) ? [...sourceVal] : { ...sourceVal };
}
} else {
target[key] = sourceVal;
}
});
});
return target;
}
使用方式与效果对比
假设:
const a = { x: 1, y: { a: 2, b: 3 } };
const b = { y: { b: 4, c: 5 }, z: 6 };
-
Object.assign(a, b) →
{ x: 1, y: { b: 4, c: 5 }, z: 6 }(y 被整个替换) -
deepAssign(a, b) →
{ x: 1, y: { a: 2, b: 4, c: 5 }, z: 6 }(y 内部被合并)
注意事项与局限
该模拟方案不处理 Symbol 键、不可枚举属性、getter/setter、原型链属性;也不克隆函数、正则、Map/Set 等复杂类型。
- 数组默认按值复制(非深度合并项),如需合并数组元素,需额外逻辑
- 日期、正则等会被原样赋值(不深拷贝),因其通常视为原子值
- 若需更健壮方案,推荐使用 Lodash 的
_.merge或结构化克隆(structuredClone)配合手动合并
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











