js中的深浅拷贝
说到深浅拷贝,我们得先来了解一下栈和堆
每个内存单元中分为两个部分,栈和堆
栈在内存的最底部,类似于一个标记,名字,分类;稳定,不可更改,空间小
堆数据,表示一组数据,可变更,数据量大,和栈一一对应
多个栈可以对应一个堆,反之不行
变量的声明,变量名存在了栈中
变量的赋值,数据存在了堆中
怎么区分深拷贝与浅拷贝,简单点来说,就是如果B复制了A,当修改B时,看A是否会发生变化,如果A也跟着变了,说明这是浅拷贝,如果A没变,那就是深拷贝。
-
基础数据类型(值传递):字符,数值,布尔,undefined
复制时,复制的是值,在栈堆关系中,栈和堆一一对应 -
复杂数据(引用传递):对象(数组,函数)
复制时,复制的是内存地址,在栈堆关系中,栈和堆可以多对一
值传递(深拷贝):复制的是变量的值
引用传递(浅拷贝):复制的是指针的指向(传递的是对象在堆内存中的内存地址)
1.浅拷贝
浅拷贝只拷贝地址,不拷贝值
浅拷贝改变对象里面的值另一个会改变,深拷贝不会改变
var obj = {name:"Admin"};
var obj2 = obj;
obj2.name = "root";
console.log(obj.name,obj2.name) //root,root
console.log(obj == obj2) //true
2.深拷贝
深拷贝只拷贝值
var a = 10;
var b = a;
console.log(b) //10
var b = 20;
console.log(a,b); //10,20
for-in实现深拷贝
var obj = {
name:"admin",
age:18,
sex:1
}
var obj2 = {}
for(var i in obj){
obj2[i] = obj[i]
}
obj2.name = obj.name
obj2.name = "root"
console.log(obj) //{name: "admin", age: 18, sex: 1}
console.log(obj2) //{name: "root", age: 18, sex: 1}
console.log(obj == obj2) //false
JSON转换实现深拷贝
- 当嵌套了多层时for-in只能在第一次有效果,这个时候可以用JSON转换
- 因为JSON.stringify()转换成字符串,是值传递
var obj = {
name:{
name2:{
name3:"admin"
}
}
}
var obj2 = JSON.parse(JSON.stringify(obj));
obj2.name.name2.name3 = "root";
console.log(obj); //admin
console.log(obj2); //root
console.log(obj == obj2); //false
js提供的方法实现深拷贝
- JSON中不允许出现函数、undefined、NaN,当出现了就会转换失败、丢失或报错
这个方法有一定的缺陷,但也能实现
var obj = {
name:{
name2:{
name3:"admin",
fn:function(){}
}
}
}
var obj2 = Object.create(obj);
//console.log(obj);
//console.log(obj2);
obj2.name = "root";
console.log(obj == obj2); //false
console.log(obj2.__proto__ == obj); //true