一、 JavaScript的数据类型
- 基本数据类型:String,Number,Boolean,Symbol,BigInt,undefined,null
基本数据类型的数据保存在栈内存中(名字与值都存在栈中) - 引用数据类型:Object、Array、Function、Date,Map,Math 等
引用数据类型的数据保存在堆内存中(名字存在栈中,值存在堆中,栈内存会提供一个引用的地址指向堆内存中的值)
深拷贝与浅拷贝只存在于引用数据类型中
二、深拷贝与浅拷贝
- 浅拷贝:只拷贝一层,仅仅是复制了引用的地址去指向内存,彼此之间的操作会互相影响
- 深拷贝:拷贝了多层,不仅新增了引用的地址,而且堆中也分配了内存,即彼此的地址都是指向不同的内存的,因此互不影响。
打比方:
- 浅拷贝就是我告诉了你保险箱的位置,你可以按照这个位置你找保险箱里的钱,由于我们都知道这个保险箱在哪,所以我们都可以往里面放钱和拿钱,如果我把钱全部拿走了,那你就从保险箱里就拿不到钱了,反之你往里面放了500,那么我就可以多拿500(O(∩_∩)O哈哈~),我们放钱和拿钱是会影响到保险箱里钱的数量的。保险箱的位置就是引用地址,保险箱里的钱就是内存值。
- 深拷贝就是,我给了你一个和我一模一样的保险箱当然里面的钱也是一模一样的,你要把保险箱放在什么位置只有你自己知道,你往你保险箱里面放钱和拿钱不会影响到我保险箱里的钱数量,相同地我往我的保险箱里拿钱和放钱也不会影响到你保险箱里的钱数量,两个保险箱互不影响。你保险箱放的位置就是新增的引用地址,你保险箱你的钱就是内存值。
三、浅拷贝的影响
改变拷贝对象的值,原对象的值也会被改变,相同的改变原对象的值,拷贝对象的值也会被改变,既相互影响。
//定义一个safeBox对象
let safeBox={
id:1158,
money:5000
}
let mySafeBox=safeBox;
//改变属性money的值
mySafeBox.money=4000;
console.log("mySafeBox: "+mySafeBox.money);
console.log("safeBox: "+safeBox.money);
safeBox.money=6000;
console.log("mySafeBox: "+mySafeBox.money);
console.log("safeBox: "+safeBox.money);
//输出
//mySafeBox: 4000,safeBox: 4000
//mySafeBox: 6000,safeBox: 6000
四、简单对象拷贝的实现方法(不属于深拷贝,此处简单对象就是只有一层的对象)
对于简单的对象拷贝操作可以采用以下两种方法,以下方法可实现一层拷贝。
1. JSON.stringify()以及JSON.parse()
let safeBox={
id:1158,
money:5000
}
let mySafeBox=JSON.parse(JSON.stringify(safeBox));
//改变属性money的值
mySafeBox.money=4000;
console.log("mySafeBox: "+mySafeBox.money);
console.log("safeBox: "+safeBox.money);
safeBox.money=6000;
console.log("mySafeBox: "+mySafeBox.money);
console.log("safeBox: "+safeBox.money);
//输出
//mySafeBox: 4000,safeBox: 5000
//mySafeBox: 4000,safeBox: 6000
2.Object.assign(target, source)
let safeBox={
id:1158,
money:5000,
}
let mySafeBox=Object.assign({}, safeBox);
//改变属性money的值
mySafeBox.money=4000;
console.log("mySafeBox: "+mySafeBox.money);
console.log("safeBox: "+safeBox.money);
safeBox.money=6000;
console.log("mySafeBox: "+mySafeBox.money);
console.log("safeBox: "+safeBox.money);
四、深拷贝
可以实现复杂对象的拷贝,即拷贝多层
遍历实现
function deepClone(obj){
//obj不是对象或数组(注意数组和对象用typeof判断都是Object类型),或者为null,则返回
if(typeof(obj)!=Object || object==null){
return obj;
}
//判断obj是对象还是数组,声明对应的,以便后面拷贝
let newObj = obj instanceof Array ? [] : {}
for(key in obj){
//属性属于对象自有的属性
if(obj.hasOwnProperty(key)){
//递归调用
newObj[key] = deepClone(obj[key]);
}
}
//遍历拷贝完所有层后返回结果
return newObj;
}