js深度对象合并,深度赋值、拷贝
程序员文章站
2022-07-02 19:14:04
问题场景平时我们在处理纯粹对象(键值对对象/JSON)时,如果使用Object.assign或者对象解构赋值,只会合并第一层的数据,而当合并嵌套对象,将会直接覆盖掉前面被合并对象里的数据,这是因为Object.assign和对象解构赋值都是只有第一层属于深拷贝,而往下都是浅拷贝,例如:var obj1 = { a: { b: 1, c: 1 } };var obj2 = { a: { b: 2 } };var obj3 = {};// Object.assignObject.assign(obj...
问题场景
平时我们在处理纯粹对象(键值对对象/JSON)时,如果使用Object.assign或者对象解构赋值,只会合并第一层的数据,而当合并嵌套对象,将会直接覆盖掉前面被合并对象里的数据,这是因为Object.assign和对象解构赋值都是只有第一层属于深拷贝,而往下都是浅拷贝,例如:
var obj1 = { a: { b: 1, c: 1 } };
var obj2 = { a: { b: 2 } };
var obj3 = {};
// Object.assign
Object.assign(obj3, obj1, obj2);
console.log(obj3); // { a: { b: 2 } }
// 解构
obj3 = { ...obj1, ...obj2 };
console.log(obj3); // { a: { b: 2 } }
可以看到,obj1里面的a属性被覆盖了,直接替换成了最后一个对象(obj2)里的a,即:{ b: 2 } 。
解决方法(代码)
// 判断是否是纯粹对象
const isPlainObject = obj => {
return Object.prototype.toString.call(obj) === '[object Object]'
}
// 主函数
function assignDeep() {
const args = Array.from(arguments);
if (args.length < 2) return args[0];
let result = args[0];
args.shift();
args.forEach(item => {
if (isPlainObject(item)) {
if (!isPlainObject(result)) result = {}
for (let key in item) {
if (result[key] && isPlainObject(item[key])) {
result[key] = assignDeep(result[key], item[key])
} else {
result[key] = item[key]
}
}
}
else if (item instanceof Array) {
if (!(result instanceof Array)) result = []
item.forEach((arrItem, arrIndex) => {
if (isPlainObject(arrItem)) {
result[arrIndex] = assignDeep(result[arrIndex])
} else {
result[arrIndex] = arrItem
}
})
}
})
return result;
}
调用示例和结果
var obj1 = { a: { b: 1, c: 1 } };
var obj2 = { a: { b: 2 } };
var obj3 = {};
// 调用assignDeep方法
assignDeep(obj3, obj1, obj2);
console.log(obj3); // { a: { b: 2, c: 1 } }
var obj4 = { a: { b: 1, c: [1, 2, 3] } };
var obj5 = { a: { b: 2, c: [1, 4], d:'d' } };
assignDeep(obj4,obj5); // { a: { b: 2, c: [1, 4], d:'d' } };
var obj6 = [1,2,3];
var obj7 = [4,5];
assignDeep(obj6, obj7); // [4,5,3]
assignDeep()方法可以解决多数常用数据类型(包括数组)的对象的赋值合并操作
本文地址:https://blog.csdn.net/cyh5d/article/details/112859352