理解深拷贝浅拷贝之前先搞清楚几个概念 什么是赋值.深拷贝.浅拷贝?
赋值:
基本数据类型:重新开辟一块栈内存所以赋值之后互不影响
引用数据类型:只是赋值的引用指针,但是指向的还是同一堆内存的对象,所以相互之间有影响。
浅拷贝:
重新在堆内存中创建内存,其中基本数据类型不影响,只能拷贝一层 对象中的子对象不进行拷贝。
深拷贝:
对象中的子对象递归拷贝,拷贝前后两个对象互不影响。
浅拷贝
先上栗子
let a = {
name: "muyiy",
book: {
tag: "这是标题",
price: "45"
}
}
function shallowcopy(obj1){
let newobj={}
for( let i in obj1 ){
newobj[i] = obj1[i]
}
return newobj
}
let b = shallowcopy(a);
console.log('b',b)
//b { name: 'muyiy', book: { tag: "这是标题", price: '45' } }
//b从a克隆获得
b.name='lily'
b.book.price = 99
console.log('a',a)
// a { name: 'muyiy', book: { tag: "这是标题", price: 99 } }
console.log('b',b)
// b { name: 'lily', book: { tag: "这是标题", price: 99 } }
//b改变了name 和 book的price属性 name为基本数据类型 改变也互不影响
//但book为引用数据类型 改变的为对应的堆内存数据 所以互相影响 b和a的book的price都改变。
其他方案 ...展开运算符 和 assign
其实这两种方法是一样的
let b = Object.assign({}, a);
let b = {...a};
深拷贝
先上栗子
let a = {
name: "muyiy",
book: {
title: "You Don't Know JS",
price: "45"
}
}
function deepcopy(target){
if (typeof target !== 'object') {
return target
}
const newobj={}
for( const key in target ){
newobj[key] = deepcopy(target[key])
}
return newobj
}
let c = deepcopy(a);
console.log('c',c)
//c { name: 'muyiy', book: { title: "You Don't Know JS", price: '45' } }
c.name="lucy"
c.book.tag = 'C的tag'
c.book.title = '新的标题'
console.log('a',a)
// a { name: 'muyiy', book: { title: "You Don't Know JS", price: '45' } }
console.log('c',c)
// c { name: 'lucy', book: { title: '新的标题', price: '45', tag: 'C的tag' }
//深拷贝 拷贝前和拷贝后 互不影响
}
但以上栗子不能处理 日期 正则 null 所以改造下栗子
function deepcopy(target){
if (typeof target !== 'object') {
return target
}
if (target === null) return target
if (target instanceof Date) return new Date(target)
if (target instanceof RegExp) return new RegExp(target)
const newobj = new target.constructor() // 创建一个新的克隆对象或克隆数组
for( const key in target ){
newobj[key] = deepcopy(target[key])
}
return newobj
}