js 深拷贝、浅拷贝深度解析

赋值操作:

javascript 复制代码
    let obj={
      a:1,
      b:[1,2,3],
      c:{
        m:2
      }
    }
    let newObj=obj
    newObj.a=2
    newObj.b.push(4)
    newObj.c.m=3
    console.log(obj,newObj);

将一个对象赋值给一个变量,其实就是将这个对象在栈内存中的引用地址复制给了这个变量,这两个对象指向堆内存中的同一个数据引用,所以,其中一个对象的值发生变化,另一个都会跟着变化。

浅拷贝的实现方法:

  1. Object.assign()

  2. Array.prototype.concat()

  3. Array.prototype.slice()

  4. 对象和数组的扩展运算符:{...obj},[...arr]

javascript 复制代码
    let obj={
      a:1,
      b:[1,2,3],
      c:{
        m:2
      },
    }
    const newObj={...obj}
    obj.a=3
    obj.b.push(4)
    console.log(obj,newObj);

浅拷贝会在堆内存中开辟新的空间。浅拷贝只复制对象的第一层属性值,如果属性值是基本类型(如数字、字符串、布尔值),则直接复制其值;如果属性值是引用类型(如数组、对象),则复制其引用地址,而不是创建一个新的对象或数组。因此,浅拷贝后的对象和原对象共享相同的引用类型的属性值,修改其中一个对象的这些属性值会影响到另一个对象。

深拷贝实现方法:

  1. JSON.parse(JSON.stringify())
javascript 复制代码
    let obj={
      a:1,
      b:[1,2,3],
      c:{
        m:2
      }
    }
    let newObj=JSON.parse(JSON.stringify(obj))
    newObj.a=2
    newObj.b.push(4)
    newObj.c.m=3
    console.log(obj,newObj);// 输出结果 obj的数据没有变化
javascript 复制代码
    let obj={
      a:null,
      b:[1,2,3],
      c:undefined,
      fn:()=>{console.log(123);}
    }
    let newObj=JSON.parse(JSON.stringify(obj))
    newObj.b.push(4)
    console.log(obj,newObj);

JSON.parse(JSON.stringify()) 可以实现深拷贝,缺点是,如果对象或数组中有函数或undefined,就会丢失。

  1. 封装深拷贝函数
javascript 复制代码
    let obj={
      a:1,
      b:[1,2,3],
      c:{
        m:2
      },
      k:undefined,
      g:null,
      fn:()=>{console.log(123);}
    }
    function deepCloneFunc(obj) {
      if(typeof obj !=='object') return obj
      const newObj=obj instanceof Array?[]:{}
      for(let key in obj){
        if(obj.hasOwnProperty(key)){
          const value = obj[key]
          newObj[key]=typeof value ==='object'?deepCloneFunc(value):value
        }
      }
      return newObj
    }
    const newObj=deepCloneFunc(obj)
    console.log(newObj);

深拷贝其实就是在堆内存中重新开辟了一块内存,创建了一个新的对象,这个对象和被拷贝的对象用于相同的属性和值,他们两个在栈内存中的引用地址也不一样,是相互独立的,因此修改任何一个对象的值,另一个都不会跟着变化。

相关推荐
F2E_Zhangmo3 小时前
基于cornerstone3D的dicom影像浏览器 第三章 拖拽seriesItem至displayer上显示第一张dicom
前端·javascript·cornerstone·cornerstone3d·cornerstonejs
gnip8 小时前
Jst执行上下文栈和变量对象
前端·javascript
拉不动的猪9 小时前
简单回顾下Weakmap在vue中为何不能去作为循环数据源,以及替代方案
前端·javascript·vue.js
How_doyou_do9 小时前
数据传输优化-异步不阻塞处理增强首屏体验
开发语言·前端·javascript
DT——10 小时前
前端登录鉴权详解
前端·javascript
界面开发小八哥10 小时前
数据可视化图表库LightningChart JS v8.0上线:全新图例系统 + 数据集重构
javascript·信息可视化·数据可视化·lightningchart
烛阴11 小时前
【TS 设计模式完全指南】从“入门”到“劝退”,彻底搞懂单例模式
javascript·设计模式·typescript
正义的大古11 小时前
OpenLayers常用控件 -- 章节六:全屏控件教程
前端·javascript·html·openlayers
正义的大古13 小时前
OpenLayers常用控件 -- 章节七:测量工具控件教程
前端·javascript·vue.js·openlayers
雲墨款哥14 小时前
一个前端开发者的救赎之路-JS基础回顾(五)-数组
前端·javascript·面试