一、前言
说到深浅拷贝,必须先提到的是JavaScript的数据类型。JavaScript的数据类型分为基本数据类型和引用数据类型。
浅拷贝和深拷贝都是对于JS中的引用类型而言的;对于基本数据类型的拷贝,并没有深浅拷贝的区别,我们所说的深浅拷贝都是对于引用数据类型而言的。
二、深浅copy
深copy:数据在copy完之后两者之间没有任何关系。
浅copy就是指数据在copy完之后两者之间还存在着关系
1,数据为数组
1)展开数据基本数据类型,属于深copy,两者之间不再有任何关系
let a = [1, 2, 3]
let b = [...a]
console.log(b) //[1,2,3]
b[0] = 12
console.log(b) //[12,2,3]
console.log(a) //[1,2,3]
2)展开数据单层对象,属于浅copy,两者之间仍存在关系
let obj = {name:"tanni",age:12}
let arr = [obj,2,3]
let newArr = [...arr]
console.log(arr)//[ { name: 'tanni', age: 12 }, 2, 3 ]
console.log(newArr)//[ { name: 'tanni', age: 12 }, 2, 3 ] 将对象展开
newArr[0].name="wangcai"
// 数据如果是对象的话,还会存在关系,属于浅copy
console.log(arr)//[ { name: 'wangcai', age: 12 }, 2, 3 ]
console.log(newArr)//[ { name: 'wangcai', age: 12 }, 2, 3 ]
2,数据为数组,遇到slice方法
1)展开数据是基本数据类型,属于深copy,两者之间没有关系
let arr = [1,2,3]
// slice表示剪切数据,得到一个新的数组,
// 首参是从哪里开始剪切,第二个参数则是到哪里结束,
// 不包括此处的数据;只有一个参数那么就剪切直到最后
let newArr = arr.slice(0)
newArr[0] = 666
console.log(arr)//[1,2,3]
console.log(newArr)// [666,2,3]
2)展开数据是单层对象,属于浅copy,两者之间存在联系
let obj = {name:"tanni"}
let arr = [obj,2,3]
let newArr = arr.slice(0)
console.log(newArr)//[ { name: 'tanni' }, 2, 3 ]
newArr[0].name = "wangcai"
console.log(arr)//[ { name: 'wangcai' }, 2, 3 ]
console.log(newArr)//[ { name: 'wangcai' }, 2, 3 ]
2,数据为对象
1)数据是单层对象,属于深copy,两者之间没有任何关系
let obj={name:"tanni",age:12}
let newObj = {...obj}
// console.log(newObj)//{name:"tanni",age:12}
newObj.age = 666
console.log(obj)//{name:"tanni",age:12}
console.log(newObj)//{name:"tanni",age:666}
2)数据是多层对象,属于浅copy,两者存在着联系
let obj = {name:"tanni",age:{number:12}}
let newObj = {...obj}
newObj.age.number = 666
console.log(obj)//{ name: 'tanni', age: { number: 666 } }
console.log(newObj)//{ name: 'tanni', age: { number: 666 } }
3)数据是多层对象,实现深copy,方法如下:
方法一:利用的是...扩展运算符
let obj = {name:"tanni",age:{number:12}}
// console.log(...obj)//需要是可迭代的数据,才可运用...
let newObj = {...obj,age:{...obj.age}}
// console.log(newObj)//{ name: 'tanni', age: { number: 12 } }
newObj.age.number = 666
console.log(obj)//{ name: 'tanni', age: { number: 12 } }
console.log(newObj)//{ name: 'tanni', age: { number: 666 } }
方法二:利用JSON.parse(JSON.stringify(obj))
let obj = {name:"tani",age:{number:12}}
let str = JSON.stringify(obj)//将JSON对象转成Json字符串
// console.log(str)//{"name":"tani","age":{"number":12}}
let newObj = JSON.parse(str)//解析JSON字符串到对象
// console.log(newObj)//{ name: 'tani', age: { number: 12 } }
newObj.age.number = 1233
console.log(obj)
console.log(newObj)//{ name: 'tani', age: { number: 1233 } }
缺点:JSON.parse(JSON.stringify(obj))的不足之处
上述方法会造成数据的丢失,数据必须完全满足json格式才OK!
let obj = {name:"tanni",age:function(){}}
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)//{name:"tanni"} 会导致数据丢失