首先深拷贝和浅拷贝只针对像 Object, Array 这样的复杂对象的。简单来说,浅拷贝只拷贝一层对象的属性,而深拷贝则递归拷贝了所有层级。
对于字符串类型,浅拷贝是对值的拷贝,对于对象来说,浅拷贝只拷贝对象的地址,并没有开辟新的栈,也就是拷贝的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变,深拷贝则是开辟新的栈空间,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
深拷贝,它不仅将原对象的各个属性逐个拷贝出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归拷贝到新对象上,如下图:
下面代码介绍一下如何实现深浅拷贝:
1、浅拷贝
<script>
//浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用
//深拷贝拷贝多层,每一级别的数据都拷贝
var obj = {
id:1 ,
name: 'andy',
msg:{
age:18
}
}
var o = {};
for (var k in obj){
// k 是属性名 obj[k]属性值
o[k] = obj[k];
}
</script>
2、实现浅拷贝的另一种方法( 语法糖的方法利用Object.assign(target,...sources) )
<script>
//浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用
//深拷贝拷贝多层,每一级别的数据都拷贝
var obj = {
id:1 ,
name: 'andy',
msg:{
age:18
}
}
var o = {};
/* for (var k in obj){
// k 是属性名 obj[k]属性值
o[k] = obj[k];
}
console.log(o); //只属于浅拷贝
console.log(obj); */
//Object.assign(target,...sources) es6新增方法可以浅拷贝
//两个参数 第一个是你要拷贝的地方 第二个是你要拷贝的对象
//新的语法糖 直接进行浅拷贝
Object.assign(o,obj); /* assign */
console.log(o); //只属于浅拷贝
console.log(obj);
</script>
3、深拷贝的实现方法
(1)、利用递归
递归方法实现深度克隆原理: 遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
<script>
var obj = {
id:1 ,
name: 'andy',
msg:{
age:18
},
color:['pink', 'red']
}
var o = {};
//封装函数完成深度拷贝 递归的操作
function dep(newobj,oldobj) {
for(var k in oldobj){
//判断属性值属于那种数据类型
//1.获取属性值
var item = oldobj[k];
//判断是否是数组
if (item instanceof Array){
newobj[k] = [];
dep(newobj[k],item)
}else if (item instanceof Object){
newobj[k] = {};
dep(newobj[k],item)
}else{
newobj[k] = item;
}
}
}
dep(o,obj);
console.log(o);
o.msg.age=20;
console.log(obj);
//深拷贝不会影响原来的数据
//深拷贝 使用遍历递归的方法
//深入到内部进行判断,直到判断到单个的对象为止
</script>
(2)、利用JSON实现深拷贝
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
}
(3)、直接使用var newObj = Object.create(oldObj)
function deepClone(initalObj, finalObj) {
var obj = finalObj || {};
for (var i in initalObj) {
var prop = initalObj[i];
if(prop === obj) {
continue;
}
if (typeof prop === 'object') {
obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);
} else {
obj[i] = prop;
}
}
return obj;
}