浅拷贝
概述:
简单说浅拷贝就是只拷贝第一层的值,其他后面的拷贝是拷贝地址。相当于拷贝了一个快捷方式,当你在原来的基础上进行更改时,后面拷贝的内容(快捷方式)都会被更改。
或者你可以理解为,浅拷贝并没有拷贝这个对象,而只是拷贝了这个对象的引用。
下面举例6种实现浅拷贝的方法:
1、Object.assign实现浅拷贝
let obj = {name:'jack',list:[1,2,3],params:{data:'ok'}}
let copyObj = Object.assign({},obj)
console.log(obj == copyObj) //false
console.log(obj.list == copyObj.list) //true
在这里说明一下,为什么obj == copyobj
为 false,为什么obj.list == copyObj.list
又为 true。
因为浅拷贝只是拷贝了第一层的值,不复制对象本身,新旧对象还是共享同一块内存。
2、Array.prototype.concat
//数组的浅拷贝
let arr = [{
username:'jack',
password:'123'
},
{
username:'tom',
password:'456'
}]
//使用concat连接
let copyArr = [].concat(arr)
console.log(copyArr == arr) //false
console.log(copyArr[0] == arr[0]) //true
3、使用数组的截取来实现浅拷贝
//使用数组的截取来实现浅拷贝
let copyArr1 = arr.slice()
console.log(copyArr1 == arr) //false
console.log(copyArr1[0] == arr[0]) //true
4、扩展运算符 …
//使用扩展运算符
let copyArr2 = [...arr]
console.log(copyArr2 == arr); //false
console.log(copyArr2[0] == arr[0]) //true
5、自定义实现函数的浅拷贝
//函数实现浅拷贝
function copy(obj){
//创建一个新的对象
let constructor = obj.constructor
let copyObj = new constructor()
for(let key in obj){
copyObj[key] = obj[key]
}
return copyObj
}
let copyArr3 = copy(arr)
console.log(copyArr3 == arr); //false
console.log(copyArr3[0] == arr[0]) //true
let copyObj1 = copy(obj)
console.log(obj == copyObj1) //false
console.log(obj.list == copyObj1.list) //true
6、使用第三方工具(lodash.js) _.clone
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script>
//浅拷贝 拷贝的对象 返回一个新的对象
let obj2 = {name:'jack',list:[1,2,3],params:{data:'ok'}}
let copyObj3 = _.clone(obj2)
console.log(obj2 == copyObj3)//false
console.log(obj2.list == copyObj3.list)//true
</script>
lodash的中文文档:
https://www.lodashjs.com/
深拷贝
概述:
深拷贝是拷贝所有的内容,这俩个内容只有里面的值是相同的,其他引用地址都是不一样的。相当于你用u盘拷贝一份资料,那么这份资料跟拷贝的那份资料是没有任何关系的,但是里面显示的内容是一样的。
下面举例3种实现深拷贝的方法:
1、序列化和反序列化 (JSON.stringify JSON.parse)
//使用序列化和反序列化
let obj = {
list:[{
name:"苹果"
},
{
name:"香蕉"
}]
}
//进行深拷贝
let copyObj = JSON.parse(JSON.stringify(obj))
console.log(copyObj == obj);//false
console.log(copyObj.list == obj.list);//false
console.log(copyObj.list[0] == obj.list[0]);//false
2、使用第三方工具 lodash.js (_.cloneDeep)
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script>
let copyObj1 = _.cloneDeep(obj)
console.log(copyObj1 == obj);//false
console.log(copyObj1.list == obj.list);//false
console.log(copyObj1.list[0] == obj.list[0]);//false
</script>
3、自定义函数实现深拷贝(用递归实现)
//自定义函数实现深拷贝(递归)
function deepClone(obj) {
//判断当前你传入的参数是否是一个对象
if (!(typeof obj == 'object' && obj)) {
return obj
}
//如果他是数组 我就赋值为数组 如果是对象就赋值为
let copyObj = obj instanceof Array ? [] : {}
//遍历传入的对象
for (let key in obj) {
//将对应的内容进行赋值
copyObj[key] = deepClone(obj[key])
}
return copyObj
}
let copyObj2 = deepClone(obj)
console.log(copyObj2);
console.log(copyObj2 == obj);//false
console.log(copyObj2.list == obj.list);//false
console.log(copyObj2.list[0] == obj.list[0]);//false
总结:浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。