深拷贝 与 浅拷贝
- 深拷贝 与 浅拷贝 的概念
- 浅拷贝的几种方式
- 深拷贝的几种方式
1:深拷贝 与 浅拷贝 的概念
- 浅拷贝
所谓浅拷贝就是在对象复制时,只是对对象中的数据成员进行简单的赋值,(复制一个对象的内存地址)而不是复制对象本身。新旧对象共享同一块内存地址。 - 深拷贝
所谓深拷贝就是完全是一份新的地址,旧对象所拥有的属性和值完全复制一份到新的地址,换句话说,修改一个对象不会影响另外一个对象。
2:浅拷贝的几种方式
- 直接赋值
const obj = {name : 'minmin',age: 18};
const obj2 = obj;
obj2.name = 'keke';
console.log(obj); // { name: 'keke', age: 18 }
- Object.assign 方法
可以把任意对象合并到前面第一个对象里面。
const obj = { name: 'minmin' };
Object.assign(obj, { age: 18 }, { gender: 'male' }, { age: 19 });
console.log(obj); // { name: 'minmin', age: 19, gender: 'male' }
Object.assign 方法也是一个浅拷贝。例如:
const obj = {
name: 'minmin',
friend: {
name: 'keke',
age: 18
}
};
const obj2 = {};
Object.assign(obj2,obj); // 也是一个浅拷贝
obj2.friend.name = 'nannan';
console.log(obj);
但是 Object.assign 拷贝的对象属性值对应的是普通数据类型,没有对象的话,就是一个深拷贝
const obj = {
name: 'minmin',
friend: 'keke'
};
const obj2 = {};
Object.assign(obj2,obj); // 深拷贝
obj2.name = 'nannan';
console.log(obj);
- ES6 的扩展运算符
const obj = {
name: 'minmin',
friend: {
name: 'keke',
age: 18
}
};
const obj2 = {...obj};
obj2.friend.name = "nannan";
console.log(obj); // { name: 'minmin', friend: { name: 'nannan', age: 18 } }
同样,如果只有一层的话,那就是一个深拷贝
const obj = {
name: 'minmin',
friend: "keke"
};
const obj2 = {...obj};
obj2.name = "nannan";
console.log(obj); // { name: 'minmin', friend: 'keke' }
- 数组的 concat 方法
const arr = [1,2,{name : 'minmin'}];
const arr2 = arr.concat();
arr2[2].name = 'keke';
console.log(arr);
-
jQuery 中提供了深浅拷贝的方法
在 jQuery 中,提供了 $.extend(deep,target,object1,objectN)deep:布尔值,true 代表深拷贝,false 代表浅拷贝; target:要拷贝的目标对象; object1:待拷贝到第一个对象的对象; objectN:待拷贝到第N个对象的对象;
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
const obj = {
name : 'minmin',
age : 18,
friend : {
name : 'keke'
}
}
const obj2 = {};
$.extend(obj2,obj);
obj2.friend.name = 'nannan';
console.log(obj);
</script>
</body>
3:深拷贝的几种方式
- jQuery 中的 $.extend 方法x
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>
const obj = {
name : 'minmin',
age : 18,
friend : {
name : 'keke'
}
}
const obj2 = {};
$.extend(true,obj2,obj);
obj2.friend.name = 'nannan';
console.log(obj);
</script>
</body>
- JSON.parse(JSON.stringify())
const obj = {
name : 'minmin',
friend : {
name : 'keke'
}
}
const obj2 = JSON.parse(JSON.stringify(obj));
obj2.friend.name = 'nannan';
console.log(obj);
上面使用的方式是JSON的方法,但是JSON和js对象还是有区别的。区别在于 JSON 表示的是数据,键所对应的值不能是函数。
但是,这种深拷贝方式有一个缺陷,如果我拷贝的对象有方法,方法不能够被拷贝。
const obj = {
name : 'minmin',
friend : {
name : 'keke'
},
sayHello : function(){},
gender : 'male'
}
const obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); // { name: 'minmin', friend: { name: 'keke' }, gender: 'male' }
- 手写递归方法来实现深拷贝
const obj = {
name: 'minmin',
friend: {
name: 'keke'
},
sayHello: function () { },
gender: 'male'
}
function deepCopy(oldObj, newObj) {
for (let key in oldObj) {
let item = oldObj[key];
if (item instanceof Array) {
newObj[key] = {};
deepCopy(item, newObj[key]);
}
else if (item instanceof Object) {
if (item instanceof Function) {
newObj[key] = oldObj[key];
} else {
newObj[key] = {};
deepCopy(item, newObj[key]);
}
}
else {
newObj[key] = item;
}
}
}
const cloneObj = {};
deepCopy(obj, cloneObj);
cloneObj.friend.name = 'nannan';
console.log(obj);
console.log(cloneObj);