javascript 中的引用数据用赋值运算符进行赋值时
复制的是变量的引用地址 这就是我们所说的浅拷贝
当进行浅拷贝时,拷贝后的变量和被拷贝变量其实都是引用的是一个地址
也就是说当一个改变时 另一个也会跟着改变
而在拷贝基本数据类型时 例如 numbar 整形时 拷贝的变量和被拷贝的变量没有直接关系,因为此时它们的拷贝是变量的值
这是拷贝基本数据类型 此时拷贝的变量和被拷贝的变量两者之间没有直接关系,一个改变了,另一个不会跟着改变
let a = 10;
b = a;
a = 100;
console.log(a);//100
console.log(b);//10
但是 当拷贝引用数据类型时 例如对象 此时问题就出来了,我们可以看到,其中一个改变 另一个也会跟着改变
let obj = {
a:1,
b:2
};
let copy = obj;
console.log(copy,obj);//{a: 1, b: 2} {a: 1, b: 2}
copy.a = 100;
console.log(copy,obj);//{a: 100, b: 2} {a: 100, b: 2}
方法一
当然我们可以对他进行深度拷贝
方法是循环遍历原始对象,然后一个接一个地复制每个属性
function copyo(obj){
let copyobj = {};
let key = "";
for(key in obj){
copyobj[key] = obj[key];
}
return copyobj;
}
let obj2 = {
a:100,
b:{
a:10,
b:10
}
}
let copyobj2 = copyo(obj2);
obj2.a = 1000;
console.log(obj2.a,copyobj2.a);//1000 100
/* 以上方法实现了一个基本的深度拷贝 我们可以发现 更改另一个值时 拷贝的变量并没有跟着改变*/
/*
但这个方法存在弊端 我们可以看到 当对象中的某个成员的也是一个对象时 这个方法就不管用了
虽然我们可以对方法进行改造 但这并没有什么大用 他并没有从根本上解决这个问题
*/
obj2.b["a"] = 2000;
console.log(obj2.b["a"],copyobj2.b["a"]);//2000 2000
方法二
我们可以使用js提供的Object.assign()这个方法来复制一个对象
let obj3 = {
a: 1,
b: 2,
c:{
a:200
}
}
let copyobj3 = Object.assign({},obj3);
obj3.a = 99;
console.log(obj3.a,copyobj3.a);//99 1
看起来这个js提供的方法的确是深度拷贝了一个对象
但是 它和上面编写的copyo方法有同样的错误
但对象的某个成员也是对象时 它只会复制其引用地址
所以这个Object.assign方法也不能完全深度拷贝
obj3.c["a"] = 20000;
console.log(obj3.c["a"],copyobj3.c["a"]);//20000 20000
完全深度拷贝
//下面给出完全深度拷贝的方案
//就是利用 JSON.parse 和 JSON.stringify 方法来实现完全深度拷贝
let obj4 = {
a: 1,
b: 2,
c:{
a:200
}
}
let copyobj4 = JSON.parse(JSON.stringify(obj4));
obj4.a = 100;
obj4.c["a"]=20000;
console.log(obj4.a,obj4.c["a"]);//100 20000
console.log(copyobj4.a,copyobj4.c["a"]);//1 200
//这样就实现了完全深度拷贝
但是它也有弊端 当对象的某个成员是方法时 它将不会被拷贝
let obj5 = {
a: 1,
b: 2,
c:{
a:200
},
d:function(){
return 123;
}
}
let copyobj5 = JSON.parse(JSON.stringify(obj5));
console.log(obj5,copyobj5);
/* '
分别输出如下
obj5:
{
a: 1,
b: 2,
c:{
a:200
},
d:function(){
return 123;
}
}
copyobj5:
{
a: 1,
b: 2,
c:{
a:200
}
}
*/