跳到主要内容

深拷贝与浅拷贝

什么是深浅拷贝

JS 分为原始类型和引用类型,对于原始类型的拷贝,并没有深浅拷贝的区别,我们讨论的深浅拷贝都只针对引用类型。

  • 浅拷贝复制的是对象的引用地址,没有开辟新的栈,复制的结果是两个对象指向同一个地址,所以修改其中一个对象的属性,另一个对象的属性也跟着改变了。
  • 深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。

这个的实现浅拷贝是一层深拷贝,多层浅拷贝,并不是完全的深拷贝

实现浅拷贝的方法 - 数组

数组实现深拷贝可以使用以下方法

  • 使用slice()
  • 使用concat()
  • ES6扩展运算符
  • 使用Array.form()
let arr = [1, 2, 3, 4, [5, 6]]

let arr1 = arr.slice()
let arr2 = [].concat(arr)
let arr3 = [...arr]
let arr4 = Array.from(arr)

image-20230731181816635

实现浅拷贝的方法 - 对象

对象实现深拷贝可以使用以下方法

  • 使用Object.assign
  • ES6扩展运算
let obj = {
name:'jl',
age: 18,
firend:{
name:'null',
age:1024
}
}

let obj1 = {...obj}
let obj2 = Object.assign({}, obj)

image-20230731182008789

实现深拷贝 - JSON.stringify

JSON.stringify 把对象转换成字符串,再用JSON.parse把字符串转换成新的对象

但是当我们的对象中有function, undefind, symbol的时候,会将其忽略

let obj = {
name:'jl',
age: 18,
firend:{
name:'null',
age:1024
},
cc: undefined,
dd: function(){
let dada = 'dasdas'
}
}

let obj1 = JSON.parse(JSON.stringify(obj))

image-20230731181850463

自己来实现一个深拷贝

//工具函数,判断是不是对象
function isObject(value){
//null,object,array都会返回object,但null是应该返回false
//function也应该返回true
const valueType = typeof value
return (value !== null) && (valueType === 'object' || valueType === 'function')
}

function deepCopy(obj){
//判断:如果是对象类型,才需要创建新对象。原始类型直接返回
if(!isObject(obj)) return obj

//判断是不是数组,是定义[],不是定义{}
const newObj = Array.isArray(obj) ? [] :{}
for(const key in obj){
if(typeof obj[key] === 'function'){
newObj[key] = obj[key]
}else{
newObj[key] = deepCopy(obj[key])
}
}

return newObj
}

const info = {
name:"a",
age:18,
friend:{
name:"b",
other: undefined,
address:{
name:"c",
detail:"d",
foo: function(){
console.log('一层一层的');
}
}
}
}

const newObj = deepCopy(info)
newObj.friend.address.name = "dwasdas"
console.log('info', info);
console.log('newObj', newObj);

image-20230731182500069