欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js深度对象合并,深度赋值、拷贝

程序员文章站 2022-03-10 21:54:32
问题场景平时我们在处理纯粹对象(键值对对象/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