什么是浅拷贝?
浅拷贝只是拷贝一层, 更深层次对象级别的只拷贝引用(地址)。
浅拷贝的特点
(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个。
(2) 对于引用类型,比如数组或者类对象,因为引用类型是引用传递,所以浅拷贝只是把内存地址赋值给了成员变量,它们指向了同一内存空间。改变其中一个,会对另外一个也产生影响。
例如:
var obj = {
id:1,
name:'andy',
mes:{
age:18
}
};
var o ={};
for(var k in obj){
//k是属性名 obj[k]是属性值
o[k] = obj[k];
}
console.log(o);
o.mes.age = 20;
console.log(obj);
打印结果:
为什么第一个输出的不是18,百度得出结论:因为console.log打印的是当前的值,展开后是最新修改后的值。
可以发现,把 obj 的mes属性赋值给 o 的时候赋值的是mes的地址,修改obj或o其中一个的mes,另一个的mes也会发生变化。
示意图:
es6新增的浅拷贝语法糖:Object.assign(o,obj); 等价于上面的for循环内容。
什么是深拷贝?
深拷贝拷贝多层,每一级别的数据都会拷贝。
深拷贝的特点
(1) 对于基本数据类型的成员对象,因为基础数据类型是值传递的,所以是直接将属性值赋值给新的对象。基础类型的拷贝,其中一个对象修改该值,不会影响另外一个(和浅拷贝一样)。
(2) 对于引用类型,比如数组或者类对象,深拷贝会新建一个对象空间,然后拷贝里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
(3) 对于有多层对象的,每个对象都需要实现 Cloneable 并重写 clone() 方法,进而实现了对象的串行层层拷贝。
(4) 深拷贝相比于浅拷贝速度较慢并且花销较大。
如:
//深拷贝拷贝多层,每一级别的数据都会拷贝
var obj = {
id:1,
name:'andy',
mes:{
age:18
},
color:['pink','red'],
};
var o ={};
//封装函数
function deepCopy(newObj, oldObj){
for(var k in oldObj){
//判断我们的属性值属于哪种数据类型
//1、获取属性值 oldObj[k]
var item = oldObj[k];
//2、判断这个值是否是数组
if(item instanceof Array){
newObj[k] = [];
deepCopy(newObj[k], item);
}else if(item instanceof Object){
//3、判断这个值是否是对象
newObj[k] = {};
deepCopy(newObj[k], item);
}else{
//4、属于简单数据类型
newObj[k] = item;
}
}
}
deepCopy(o,obj);
console.log(o);
示意图如下:
引用类型的值都是 Object 的实例。引用类型有:Object类型,Array类型,Date类型,RegExp类型(正则),function类型。还有基本包装类型,也是一种引用类型。ECMAScript还提供了 3个特殊的引用类型:Boolean、Number和String。
附:
引用类型的值都是 Object 的实例。引用类型有:Object类型,Array类型,Date类型,RegExp类型(正则),function类型。还有基本包装类型,也是一种引用类型。ECMAScript还提供了 3个特殊的引用类型:Boolean、Number和String。