1、浅拷贝
浅拷贝只拷贝一层,更深层次对象级别的只拷贝引用(就是只拷贝地址)
1、原生js方法的浅拷贝
<script>
var obj = {
id:1,
name:'andy',
// msg是一个对象,对象会在内存中新开辟一个空间,存放age:18;
// 浅拷贝只是把msg的地址拷给了o,这个地址指向的还是原来的obj里面存的数据,所以对象o里面和对象obj里面的msg指向的是同一个数据
// 如果此时修改了o里面的msg,也会影响obj里面的msg的数据,因为他们指向的是同一个地址
msg:{
age:18
}
};
var o = {
};
for (var k in obj){
// k 是属性名 obj[k] 是属性值
// 拷贝的是地址,
o[k]= obj[k];
}
console.log(o);
// 此时修改了o里面的msg,obj 和 o 里面的msg的age都变成20
o.msg.age = 20;
console.log(obj);
console.log(o);
</script>
2、Object.assign()
(这是ES6新增的)
Object.assign(target,…sources)
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象。它将返回目标对象。
target:目标对象 (就是你要拷贝给谁)
souce:源对象(可多个) (就是你要拷贝哪个对象)
<script>
var obj = {
id:1,
name:'andy',
// msg是一个对象,对象会在内存中新开辟一个空间,存放age:18;
// 浅拷贝只是把msg的地址拷给了o,这个地址指向的还是原来的obj里面存的数据,所以对象o里面和对象obj里面的msg指向的是同一个数据
// 如果此时修改了o里面的msg,也会影响obj里面的msg的数据,因为他们指向的是同一个地址
msg:{
age:18
}
};
var o = {
};
Object.assign(o,obj);
//第一个参数就是 目标对象,就是要把数据拷贝给o
//第二个参数就是 源对象,就是从哪一个对象里面拷贝,这里就是obj
//就是把obj 拷贝给 o
console.log(o);
// 此时修改了o里面的msg,obj 和 o 里面的msg的age都变成20
o.msg.age = 20;
console.log(obj);
console.log(o);
</script>
2、深拷贝
深拷贝拷贝多层,每一级别的数据都会拷贝
// 深拷贝拷贝多层,每一级别的数据都会拷贝
// obj这个对象里面有另一个对象msg,msg会新开辟一个空间A,深拷贝就是就是把新开辟的这个空间A复制一份再新开辟一个空间B
// 然后把拷贝完的这个空间B再给对象 o ,这样A,B两个空间互相不干扰,修改了 o 里面的数据也不会影响 obj 里面的数据了
var obj = {
id:1,
name:'andy',
msg:{
age:18
},
color:['orange','deeppink']
};
var o = {
};
// 封装函数
// 这个函数有两个参数,一个是旧对象oldobj,一个是新对象newobj,把旧对象拷贝给新对象
// 里面有不同的值,所以要先进性数据类型的判断
function deepCopy(newobj,oldobj) {
for(var k in oldobj){
// 判断属性值属于哪种数据类型
// 1、获取属性值 oldobj[k]
var item = oldobj[k];
// 2、判断这个值是否是数组
if(item instanceof Array){
newobj[k] =[];
// 相当于新对象 o 里面的属性color等于一个空的数组,也就是说这个属性里面存的必须是一个数组形式的
// o.color = [];
// 此时就可以利用递归函数 ,把属性值item给属性名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);
o.msg.age = 20;
// 修改了o 的msg也不会对obj有影响
console.log(obj);