深拷贝与浅拷贝
深拷贝
- 深拷贝在进行深拷贝时,会拷贝所有的属性,并且如果这些属性是对象,也会对这些对象进行深拷贝,直到最底层的基本数据类型为止
深拷贝的方法:
- for in 遍历+递归的方式
<script>
// 将一个对象里面的内容只拷贝一层
const obj = {
name:"张三",
age:18,
info:{
address1:"深圳",
address2:"江西"
},
hobby:["唱","条","rap","篮球","music"]
}
const newObj = {}
// 深拷贝
function fn(newObj,oldObj){
for(let key in oldObj){
if(Object.prototype.toString.call(oldObj[key]) === '[object Object]'){
newObj[key] = {} //相对于创建一个新的空间
// 递归
fn(newObj[key],oldObj[key])
}
else if(Object.prototype.toString.call(oldObj[key]) === '[object Array]'){
newObj[key] = [] //相对于创建一个新的空间
fn(newObj[key],oldObj[key]) //使用递归
}else{
// newObj[name] = oldObj[name] => 此时
newObj[key] = oldObj[key]
}
}
}
fn(newObj,obj)
console.log(newObj,obj);
console.log(newObj === obj);
console.log(newObj.info === obj.info);
</script>
- JSON数据转换的方式
但是深拷贝用此方法可能会造成对象内方法的丢失
<script>
// 将一个对象里面的内容只拷贝一层
const obj = {
name:"张三",
age:18,
info:{
address1:"深圳",
address2:"江西"
},
hobby:['唱','跳','rap','篮球','music']
}
// 用JSON数据也可以实现深拷贝
const jsonstr = JSON.stringify(obj)
const newObj = JSON.parse(jsonstr) //深拷贝
console.log(newObj,obj);
console.log(newObj === obj);
console.log(newObj.info === obj.info);
</script>
- 引用lodash.js 创建深拷贝 const newObj = _.cloneDeep(obj)
<script src="./lodash.js"></script>
<script>
const obj = {
name:"张三",
age:18,
info:{
address1:"深圳",
address2:"江西"
},
hobby:["唱","跳","rap","篮球","music"]
}
const newObj = _.cloneDeep(obj)
console.log(newObj,obj);
console.log(newObj === obj);
console.log(newObj.info === obj.info);
</script>
- 扩展运算符
当元素是一层数组或是对象时,也即元素只是简单类型的元素,那么三个点此时是深拷贝
此处obj1和obj没有关系
浅拷贝
- 浅拷贝只会拷贝对象的第一层属性,如果这些属性是对象,则不会对这些对象进行拷贝,而是直接复制对象的引用。这意味着,对于浅拷贝后的对象,如果原对象的属性值发生了变化,浅拷贝后的对象的属性值也会跟着发生变化
浅拷贝的方法:
- for in 遍历+递归的方式
<script>
// 将一个对象里面的内容只拷贝一层
const obj = {
name:"张三",
age:18,
info:{
address1:"深圳",
address2:"江西"
},
hobby:["唱","跳","rap","篮球","music"]
}
/* const newObj = obj //这种方式 => 不叫做拷贝 它只是把obj存储的地址复制一份 交给newObj */
const newObj = {}
// 需要遍历 将obj里面的内容都遍历一遍 赋值给newObj
for(let key in obj){
newObj[key] = obj[key]
}
console.log(obj === newObj); //false
console.log(obj.info == newObj.info); //true 因为只拷贝第一层 后面层级的引用指向同一个堆内存中地址
</script>
- 三点运算符
<script>
// 将一个对象里面的内容只拷贝一层
const obj = {
name: "张三",
age: 18,
info: {
address1: "深圳",
address2: "江西"
},
hobby: ["唱", "跳", "rap", "篮球", "music"]
}
/*
三点运算符实现浅拷贝
*/
const newObj = { ...obj } //浅拷贝
console.log(obj === newObj); //false
console.log(obj.info == newObj.info); //true
</script>
- Object.assign() 可以把任意多个的源对象自身的可枚举属性拷贝给目标对象
<script>
// 将一个对象里面的内容只拷贝一层
const obj = {
name: "张三",
age: 18,
info: {
address1: "深圳",
address2: "江西"
},
hobby: ["唱", "跳", "rap", "篮球", "music"]
}
/*
Object.assign(浅拷贝的目标对象,浅拷贝的源对象)
*/
const newObj = {}
Object.assign(newObj,obj) //浅拷贝
console.log(obj,newObj);
console.log(obj === newObj); //false
console.log(obj.info == newObj.info); //true
</script>
- 引用lodash.js 创建浅拷贝 const newObj = _.clone(obj)
<script src="./lodash.js"></script>
<script>
// 将一个对象里面的内容只拷贝一层
const obj = {
name:"张三",
age:18,
info:{
address1:"深圳",
address2:"江西"
},
hobby:["唱","跳","rap","篮球","music"]
}
const newObj = _.clone(obj) //浅拷贝
console.log(obj,newObj);
console.log(obj === newObj); //true
console.log(obj.info === newObj.info); //false
</script>
lodash.js文件可以通过Boot CDN官网进行下载或者直接请求网络链接
使用方法进入Lodash官网搜索深拷贝和浅拷贝的使用
两者的区别
- 深拷贝生成的新的对象和原对象没有关系
- 对于浅拷贝生成的新对象,如果原对象发生改变,只要修改的不是第一层变量,那么拷贝的新对象会随之改变,因为拷贝的是对象引用,与原对象属性在堆内存中指向同一个地址,但是如果改变的是第一层的变量,那么新对象就不会修改,因为在栈内存中它们是不同的属性,互不影响