简单聊聊 深拷贝 VS 浅拷贝

31 阅读2分钟

理解深拷贝浅拷贝之前先搞清楚几个概念 什么是赋值.深拷贝.浅拷贝?

赋值:

基本数据类型:重新开辟一块栈内存所以赋值之后互不影响
引用数据类型:只是赋值的引用指针,但是指向的还是同一堆内存的对象,所以相互之间有影响。

浅拷贝:

重新在堆内存中创建内存,其中基本数据类型不影响,只能拷贝一层 对象中的子对象不进行拷贝。

深拷贝:

对象中的子对象递归拷贝,拷贝前后两个对象互不影响。

浅拷贝

先上栗子

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
}