对象的深拷贝与浅拷贝的区别如下:
浅拷贝:仅仅复制对象的引用,而不是对象本身;
深拷贝:把复制的对象所引用的全部对象都复制一遍。
深拷贝的几种方法如下:
1. 利用 JSON.stringify() JSON.parse() 序列化和反序列
代码如下:
function deepCopy(obj){
let data = JSON.stringify(obj)
let newData = JSON.parse(data)
return newData
}
先将需要拷贝的对象进行JSON字符串化,然后再pase解析出来,赋给另一个变量,实现深拷贝。
缺点:部分数据类型在JSON字符串化后会丢失;
这是因为JSON在执行字符串化的这个过程时,会先进行一个JSON格式化,获得安全的JSON值;
因此如果是非安全的JSON值,就会被丢弃掉。其中undefined、function、symbol这三种类型的值就是非安全的,所以格式化后,就被过滤掉了
set、map这种数据格式的对象,也并没有被正确处理,而是处理成了一个空对象。
2. Object.assign(target, source1, source2)
可以用于对象合并,将源对象的所有可枚举属性,复制到目标对象上。
代码如下:
var data = {
a: "123",
b: 123,
c: true,
d: [43, 2],
e: undefined,
f: null,
g: function() { console.log("g"); },
h: new Set([3, 2, null]),
i: Symbol("fsd"),
k: new Map([ ["name", "张三"], ["title", "Author"] ])
};
var newData = Object.assign({},data)
console.log(newData)
newData 则为深拷贝后的对象;
这个方法也有一个缺点:
这种方式的拷贝,如果源目标对象中某个属性值是对另一个对象的引用,那么这个属性的拷贝仍然是对引用的拷贝。
var test = { name: '张三' }
var data = {
a: 123,
b: test
}
var newData = Object.assign({},data)
console.log(newData)
// { a: 123, b: { name: '张三' }}
test.age = 18
console.log(newData)
// { a: 123, b: { name: '张三', age: 18 }}
3. 迭代递归
参考别人的代码:
function deepCopy(data) {
if(typ data !== 'object' || data === null){
throw new TypeError('传入参数不是对象')
}
let newData = {};
const dataKeys = Object.keys(data);
dataKeys.forEach(value => {
const currentDataValue = data[value];
// 基本数据类型的值和函数直接赋值拷贝
if (typ currentDataValue !== "object" || currentDataValue === null) {
newData[value] = currentDataValue;
} else if (Array.isArray(currentDataValue)) {
// 实现数组的深拷贝
newData[value] = [...currentDataValue];
} else if (currentDataValue instanc Set) {
// 实现set数据的深拷贝
newData[value] = new Set([...currentDataValue]);
} else if (currentDataValue instanc Map) {
// 实现map数据的深拷贝
newData[value] = new Map([...currentDataValue]);
} else {
// 普通对象则递归赋值
newData[value] = deepCopy(currentDataValue);
}
});
return newData;
}