深浅拷贝
浅拷贝
指的是赋值拷贝 引用数据类型的内存地址,如果是简单数据类型拷贝的是值, 引用数据类型拷贝的是地址,也就是说单层对象没问题, 多层嵌套就会新数组改变,原数组也会跟着改变,影响最初的值.
特点
一个修改 另一个也改变
本质上 是有一个引用数据类型
多个变量中存储的是相同的内存地址
深拷贝
指的是赋值拷贝 引用数据类型的数据数值,深浅拷贝只针对引用数据类型, 对于简单数据类型直接拷贝他的值, 对于引用数据类型, 在堆内存中开辟一块内存用于存放复制的对象, 并把原有的对象类型数据拷贝过来, 这两个对象互相独立, 属于两个不同的内存地址, 修改其中一个,另一个不会发生改变
注意:
- 先数组, 后对象
- 实现深拷贝的方式
// 引用数据类型 数组
// 变量arr中存储的是 数组的内存地址
const arr = [100,200,300,400,500];
// 将数组arr中存储的内存地址 赋值给变量newArr1 存储
// 这里执行的是 浅拷贝
const newArr1 = arr ;
// 创建一个新数组
const newArr2 = [];
// 深拷贝的执行结果
// 将 原始数组arr 中 每一个数据 赋值给 新数组newArr2 存储
// 变量newArr2 中 存储的是 和 变量arr 不同的内存地址
// 只是 两个不同的存储空间中 存储了相同的数据数值
// 一个变量对应的存储空间中 存储的数据数值改变
// 另一个存储空间 不会受到影响
newArr1.forEach(item=>{
newArr2.push(item);
})
// 浅拷贝的执行结果
// 也就是 变量arr 和 变量newArr1 中 存储的是 相同的一个数组的内存地址
// 调用的是同一个内存空间中存储的数据数值
// 也就是 一个变量执行操作 另一个变量的调用也会受到影响
arr[0] = '北京' ;
console.log( arr );
console.log( newArr1 );
console.log( newArr2 );
实际项目中的深浅拷贝
const arr = [100,200,300,[400,500,600,[700,800,900]]];
const obj = { name:{n1:'张三' , n2:'张三三' , n3:'张33333'} , age:18 , sex:'男' , addr:['北京' , '上海' , '广州'] };
// // 如果只是直接循环遍历 一维是深拷贝 多维是浅拷贝
// const newArr = [] ;
// arr.forEach( item => newArr.push( item ) );
// arr[0] = '北京' ;
// arr[3][0] = '上海' ;
// console.log( arr );
// console.log( newArr );
// 实际项目中的深拷贝1 递归函数 完成深拷贝
// 有一个新数组
const newArr = [] ;
// 将 原始数组arr 中的数据 深拷贝新数组newArr中
deepCopy( arr , newArr );
arr[3][0] = '上海' ;
console.log( arr );
console.log( newArr );
const newObj = {} ;
deepCopy( obj , newObj );
obj.addr[0] = 600 ;
console.log( obj );
console.log( newObj );
// 递归完成深拷贝的函数
function deepCopy( oldVal , newVal ){
// oldVal 是 原始数据结构
// newVal 是 新数据结构
// for...in循环遍历原始数据结构
for( let key in oldVal ){
// key 是 数组的索引下标 或者 对象的键名
// oldVal[key] 是 数组的数据数值 或者 对象的键值
if( Object.prototype.toString.call( oldVal[key] ) === '[object Array]' ){
// 如果数据是 数组类型
// 新数据结构 起始应该是 空数组
newVal[key] = [] ;
// 再次调用函数 执行 深拷贝
deepCopy( oldVal[key] , newVal[key] );
}else if( Object.prototype.toString.call( oldVal[key] ) === '[object Object]' ){
// 如果数据是 对象类型
// 新数据结构 起始应该是 空对象
newVal[key] = {} ;
// 再次调用函数 执行 深拷贝
deepCopy( oldVal[key] , newVal[key] );
}else{
// 如果数据不是 对象 也不是 数组
// 直接 赋值拷贝
newVal[key] = oldVal[key] ;
}
}
}
// // 数组的数据类型判断结果 [object Array]
// console.log( Object.prototype.toString.call( [] ) );
// // 对象的数据类型判断结果 [object Object]
// console.log( Object.prototype.toString.call( {} ) );
// 实际项目中的深拷贝2 json字符串
// 将 原始数组/原始对象 转化为 json字符串
// 再将 json字符串 还原成对应的数据结构 赋值给变量存储
// 变量中存储的就是新的应用数据类型
const a = JSON.parse( JSON.stringify( arr ) );
arr[3][0] = '北京';
console.log( a );
console.log( arr );
const b = JSON.parse( JSON.stringify( obj ) );
b.addr[0] = 300 ;
console.log( b );
console.log( obj );