最近在面试新人,问了一个问题,让说一下 深拷贝浅拷贝,感觉说的很官方,但是在具体就说不上来了,所以觉得这个还是应该整理一下,利人利己.
概念解释
浅克隆 :不仅赋值,而且赋予了内存地址[只复制了引用]
深克隆: 赋值,内存地址不同
区别:浅克隆和深克隆最大的区别就是对引用值的处理了,即浅克隆之后你改我也改,深克隆之后你改我不改。
标题堆栈粗解
- 原始值(栈数据stack):Number,Boolean(false/true),String,undefined,null
- 引用值(堆数据heap):Array,Object,function ··· Date,RegExp
栈数据和堆数据
栈(stack)会自动分配内存空间,会自动释放。
堆(heap)动态分配的内存,大小不定也不会自动释放
基本类型(简单的数据段,存放在栈里面,占固定大小的空间)
引用类型,值大小不固定,栈内存中存放地址指向堆内存中的对象。是按引用访问的。
所以浅克隆,就是只克隆栈,
深克隆,就是不光克隆了栈,也克隆了堆.
举例分析
举个列子,你定义了一个变量 a, 赋值为 3,有定义了一个变量b,将a赋值给b,在之后改变b的值为4,输入 a, b, a=3, b=4
- 浅拷贝举例1
var a = 3;
var b = a;
b = 4;
console.log(a) // 3
console.log(b) // 4
创建a = 3—> 3 是数字–>属于基本类型–>基本类型存放在栈里面–>将 a 赋值给b —>在栈里又有一个内存是 b—>b的值是3—>b = 4 ---->栈里找到b=3,将3变为4
所以最后的输入结果是 a = 3,b = 4
浅拷贝举例2
var a = {
name:"张三"
};
var b = a;
b.name = "李四";
console.log(a) // {name:"李四"}
console.log(b) // {name: "李四"}
实现深拷贝方法
1.递归遍历,
原理:讲对象逐层遍历,遍历到基本类型,在进行拷贝。
function deepClone(obj){
let objClone = Array.isArray(obj)?[]:{}; if(obj && typeof obj==="object"){ for(key in obj){ if(obj.hasOwnProperty(key)){ //判断ojb子元素是否为对象,如果是,递归复制
if(obj[key]&&typeof obj[key] ==="object"){
objClone[key] = deepClone(obj[key]);
}else{ //如果不是,简单复制
objClone[key] = obj[key];
}
}
}
} return objClone;
}
let a=[1,2,3,4],
b=deepClone(a);
a[0]=2;
console.log(a,b);
2.转正字符串,在进行拷贝,但是如果拷贝对象里有方法,不可以使用
function deepClone(obj){
let _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone
}
let a=[0,1,[2,3],4],
b=deepClone(a);
a[0]=1;
a[2][0]=1;
console.log(a,b);