自己不太了解这一块,查了一些博客加实践后感觉懂了,记录一下,防止忘记
先了解一下js中数据存储的方式
js有8中数据类型:Number String Boolean undefined null(返回的是Object) Object bigInt (表示比Number更大的值)symbol(表示不会改变的唯一值)其中后两种是ES6新增加的,具体使用查MDN。
数据类型又分为简单数据类型和引用数据类型。
-
简单数据类型存放在栈里,直接开辟空间存储值。
-
引用数据类型将属性名存在栈内存中,值存在堆内存中,但是堆内存会提供一个引用的地址指向堆内存中的值。如图所示。
栈:由操作系统自动分配释放,存放函数的参数值,局部变量等值,类似数据结构中的栈。
堆:一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收,分配方式类似于链表。
进入正题
,JS中的深浅拷贝是什么意思?
- 复杂数据类型赋值时,新的对象与原本对象会指向同一堆的地址,改变新对象会使原对象一同改变,这是浅拷贝。
//浅拷贝
let a = [0,1,2,3,4];
b = a;
console.log(a===b);//true,地址相同
a[0]=1;
console.log(a,b);//0,1,2,3,4
//b也和a一起被改变了
- 而简单数据类型赋值给另一方时,会重新开辟空间,不存在地址相同的情况。当改变赋值运算其中一方的值不会改变另一方的值,这是深拷贝。但通常我们说要实现深拷贝的时候一般是针对于较为复杂的Object类型,所以现在的问题就是如何实现对象的深拷贝。
- 用递归的方法简单实现
// 深拷贝简单实现
// 如果数据层很深,会栈溢出
function deepClone(obj){
// 开辟一个新空间
let objClone = Array.isArray(obj)?[]:{};
console.log( typeof obj);
console.log( objClone);
if(obj && typeof obj === 'object'){
//是否存在obj,obj是否为对象
for(key in obj){
if(obj.hasOwnProperty(key)){
console.log('key',key,'key值',obj[key]);
if(obj[key]&& typeof obj[key] === 'object')
{
objClone[key] = deepClone(obj[key]);
}else{
objClone[key]=obj[key];
}
}else{ return obj}//不为对象直接抛出
}
}
return objClone;
}
let a = [2,3,4];
b = deepClone(a);
console.log(a===b);//false
a[0]=1;
console.log(a,b)
结果:
- 利用JSON转换
Json对象:{“name”:“shily”,“sex”:“女”,“age”:“23”}
是Object类型,对象的值可以用对象.属性访问
Json字符串:
‘{“name”:“shily”,“sex”:“女”,“age”:“23”}’
是String,不能通过对象.属性访问
字符串=>对象,转化:通过JSON.parse()
对象=>字符串,JSON.stringify()
//用Json的方法实现
//会弄丢function,忽略函数和undefined
let _obj =JSON.stringify(obj);//把对象转换成字符串
objClone = JSON.parse(_obj);//把字符串转换成对象
return objClone;