深拷贝-深拷贝与浅拷贝的区别-深拷贝的常用方法

讲深拷贝的前言

数据类型

基 本 数 据 类 型 : n u m b e r , s t r i n g , b o o l e a n , n u l l , u n d e f i n e d , s y m b o l \color{skyblue}{基本数据类型:number, string, boolean, null, undefined, symbol} number,string,boolean,null,undefined,symbol
引 用 数 据 类 型 : o b j e c t , a r r a y , f u n c t i o n \color{skyblue}{引用数据类型:object, array, function} object,array,function

区别

基 本 类 型 没 有 属 性 和 方 法 , 保 存 在 栈 区 。 \color{skyblue}{基本类型没有属性和方法,保存在栈区。}
引 用 类 型 有 属 性 和 方 法 , 保 存 在 栈 区 和 堆 区 。 \color{skyblue}{引用类型有属性和方法,保存在栈区和堆区。}
引 用 类 型 的 地 址 保 存 在 栈 区 , 数 据 保 存 在 堆 区 , 栈 区 的 地 址 指 向 堆 区 的 数 据 \color{red}{引用类型的地址保存在栈区,数据保存在堆区,栈区的地址指向堆区的数据}

什么是深拷贝、浅拷贝?

深拷贝:只有引用类型才涉及深拷贝,深拷贝指的是将引用类型的地址和数据全都拷贝到新的内存空间
浅拷贝:简单理解就是直接把引用类型赋值给一个新的变量,直接赋值的操作就是浅拷贝

深拷贝与浅拷贝的区别

浅拷贝只是拷贝了引用类型的地址,新拷贝的地址还是指向原来的数据,对新数据的修改会影响到原数据一起修改
深拷贝是拷贝了引用类型的地址和数据到新的内存空间,原地址指向原数据,新地址指向新数据,对新数据的修改不会影响原数据

为什么要深拷贝

先看浅拷贝会带来什么问题
let obj = {
    
    
    a: 1,
    b: 2
}
let newObj = obj
newObj.a = 3
console.log(obj.a, newObj == obj)//3 true
可 以 看 到 浅 拷 贝 在 修 改 新 对 象 n e w O b j 的 时 候 会 改 变 原 来 的 对 象 o b j \color{red}{可以看到浅拷贝在修改新对象newObj的时候会改变原来的对象obj} newObjobj
所 以 当 我 们 期 望 原 对 象 不 会 被 改 变 时 , 就 需 要 用 到 深 拷 贝 \color{red}{所以当我们期望原对象不会被改变时,就需要用到深拷贝}

深拷贝的常用方法

1、JSON.parse(JSON.stringify(obj)) 此 方 法 适 用 于 对 象 的 属 性 值 都 为 基 本 数 据 类 型 时 的 深 拷 贝 ( u n d e f i n e d 不 能 被 拷 贝 ) \color{red}{此方法适用于对象的属性值都为基本数据类型时的深拷贝(undefined不能被拷贝)} (undefined)
let obj = {
    
    
    a: 1,
    b: 'str',
    c: false,
    d: null
}
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj, newObj == obj)//{a: 1, b: "str", c: false, d: null} false
2、递归深拷贝
function deepClone(sourceObj) {
    
    
    if (!sourceObj || typeof sourceObj !== 'object' || Object.keys(sourceObj).length === undefined) {
    
    
        return sourceObj
    }
    const cloneObj = sourceObj instanceof Array ? [] : {
    
    }
    Object.keys(sourceObj).forEach(obj => {
    
    
        cloneObj[obj] = deepClone(sourceObj[obj])
    })
    return cloneObj
}
注 意 : 数 组 的 部 分 方 法 虽 然 能 返 回 一 个 新 的 数 组 , 但 他 本 质 上 还 是 浅 拷 贝 \color{red}{注意:数组的部分方法虽然能返回一个新的数组,但他本质上还是浅拷贝} :

例如Array.from()、slice()、concat()

let obj = [{
    
    
    a: function () {
    
    
        console.log(this)
    },
    b: {
    
    
        id: 1
    },
    c: [1, 2, [3, [4, 5]]]
}]
let newObj = Array.from(obj)
newObj[0].c = 1
console.log(obj[0].c, newObj == obj)//1 false

可以发现,虽然新数组跟原数组不等,但是修改修改了新数组,原数组的值也会跟着变化

如 有 问 题 或 错 误 , 欢 迎 指 正 \color{skyblue}{如有问题或错误,欢迎指正}

猜你喜欢

转载自blog.csdn.net/zty867097449/article/details/108143834