JS的深拷贝和浅拷贝的几种实现方案

小温侯
• 阅读 742

深拷贝和浅拷贝

**在日常开发过程中,我们经常会涉及到数据的拷贝。有时候会有困惑,到底是使用深拷贝还是浅拷贝,
我们先来明确一下什么是深拷贝什么是浅拷贝**

关于对深拷贝和浅拷贝的定义:

浅拷贝
  • 如果属性都是基本数据类型,那么就是拷贝基本数据类型的值
  • 如果属性里面有引用数据类型,那么拷贝的就是内存地址,这时修改新对象,对导致原对象也被修改了

    深拷贝
  • 如果属性都是基本数据类型,那么就是拷贝基本数据类型的值
  • 如果属性里面有引用数据类型( 对象 ),那么会创建新的对象,将原对象的属性和值拷贝出来,放到新对象里面,并且修改新对象不会对原对象产生影响
浅拷贝的实现方案

ES6的展开运算符

 /*
       使用ES6的展开运算符
   */
   const arr = [1,2,3,4]
   const obj = {name:"张三",age:12}
   const newArr = [...arr]
   const newObj = {...obj}
   console.log(newArr) // [1, 2, 3, 4]
   console.log(newObj) // {name: '张三', age: 12}

Object.assign(目标对象,拷贝源)

  /*
        Object.assign(target,sources)
            第一个参数:目标对象 ( 拷贝到的对象 )
            第二个参数:拷贝源 ( 要被拷贝的原对象 )
    */
      const obj = { name: '张三', age: 10 }
      const arr = [1, 2, 3]
      const newObj = Object.assign({}, obj)
      const newArr = Object.assign([], arr)
      console.log(newObj) // {name: '张三', age: 10}
      console.log(newArr) // [1, 2, 3]
      

使用浅拷贝来拷贝对象里面还有对象的数据时产生的影响

      /*
           如果对象里面有引用数据类型( 就是对象里面包含了对象 ),使用浅拷贝,
           那么修改了拷贝出来的对象,会导致原对象也被修改了
      */
      const obj = {
        name: '张三',
        age: 10,
        info: {
          address: '湖北',
          postcode: '430000',
        },
      }
      const newObj = { ...obj }
     // 如果修改了对象里面的引用数据类型的数据,会导致原对象也被修改
      newObj.info.postcode = '410000'
      console.log(newObj.info) // {address: '湖北', postcode: '410000'
      console.log(obj.info)   // {address: '湖北', postcode: '410000'}
深拷贝的实现方案

JSON.parse(JSON.stringify(sources))

      /*
           如果对象里面有引用数据类型( 就是对象里面包含了对象 ),使用深拷贝,
           那么修改了拷贝出来的对象,不会导致原对象也被修改了
      */
      const obj = {
        name: '张三',
        age: 10,
        info: {
          address: '湖北',
          postcode: '430000',
        },
      }

      const newObj = JSON.parse(JSON.stringify(obj))
      newObj.info.postcode = '410000'
      console.log(newObj.info) // {address: '湖北', postcode: '410000'}
      console.log(obj.info) // {address: '湖北', postcode: '430000'}

使用递归拷贝

    // object:要被拷贝的对象  hash默认创建一个空map
      function deepCopy(object, hash = new Map()) => {
      // 判断是否是引用数据类型,如果不是直接返回
        if (typeof object != 'object') return object
        // 判断 hash里面是否有这个key,如果有也返回
        if (hash.get(object)) {
          return object
        }
        // 能执行到这里的只有数组和对象
        // object.constructor指向构造函数本身,通过构造函数创建对象或者数组
        let container = new object.constructor()
        // 向map中存这个key,以后循环的时候如果这个key存在,那么就不在继续循环
        hash.set(object, container)
        for (let key in object) {
         // 如果 object是对象那么,这里的key表示对象的键
         // 如果是object是数组,那么key表示数组元素的下标
         // 然后这边递归调用,直到object里面没有引用数据类型,那么递归结束
          container[key] = deepCopy(object[key], hash)
        }
        // 最后返回 这个对象或者数组
        return container
      }
      
       const obj = {
        name: '张三',
        info: {
          age: 10,
        },
      }
      const newObj = deepCopy(obj)
      newObj.info.age = 20
      console.log(newObj.info) // {address: '湖北', postcode: '410000'
      console.log(obj.info)   // {address: '湖北', postcode: '410000'}
      

本文内容主要包括:

  • 浅拷贝和深拷贝的区别
  • 实现浅拷贝的两种方式

    • es6的展开运算符
    • Object.assign()
  • 实现深拷贝的两种方式

    • 1: JSON.parse(JSON.stringify)实现深拷贝
    • 2: 使用递归函数进行深拷贝
点赞
收藏
评论区
推荐文章
翼
4年前
ES6的解构赋值是深拷贝or浅拷贝?
面试时候有面试官问到ES6的解构赋值是深拷贝还是浅拷贝?,这里做一个总结.ES6的解构赋值,大家应该都清楚,就是可以快速取出数组或者对象中的值;我们先来看一个使用案例:更多的解构赋值知识可以查看:https://es6.ruanyifeng.com/docs/destructuring那么,ES6的解构赋值到底是深拷贝还是浅拷贝呢?我们先来看一下深拷贝和浅
Wesley13 Wesley13
3年前
java 复制Map对象(深拷贝与浅拷贝)
java复制Map对象(深拷贝与浅拷贝)CreationTime2018年6月4日10点00分Author:Marydon1.深拷贝与浅拷贝  浅拷贝:只复制对象的引用,两个引用仍然指向同一个对象
晴空闲云 晴空闲云
3年前
也谈JavaScript浅拷贝和深拷贝
网上关于这个话题,讨论有很多了,根据各路情况我自己整理了一下,最后还是能接近完美的实现深拷贝,欢迎大家讨论。javascript中的对象是引用类型,在复制对象的时候就要考虑是用浅拷贝还是用深拷贝。直接赋值对象是引用类型,如果直接赋值给另外一个对象,那么只是赋值一个引用,实际上两个变量指向的同一个数据对象,如果其中一个对象的属性变更,那么另外一个也会变更。示
Java对象拷贝原理剖析及最佳实践
作者:宁海翔1前言对象拷贝,是我们在开发过程中,绕不开的过程,既存在于Po、Dto、Do、Vo各个表现层数据的转换,也存在于系统交互如序列化、反序列化。Java对象拷贝分为深拷贝和浅拷贝,目前常用的属性拷贝工具,包括Apache的
菜园前端 菜园前端
2年前
带你了解JS对象的浅拷贝和深拷贝
以下主要介绍了正常情况下的拷贝、浅拷贝、深拷贝三种方式的区别。正常拷贝:复制一个对象,它们的内存地址是相同的浅拷贝:拷贝对象的第一层属性深拷贝:拷贝对象多层的属性正常拷贝假设我们要复制一个对象,如果不对其进行深拷贝,那么改变其中一个对象后,另外一个对象也会
Souleigh ✨ Souleigh ✨
4年前
实现深拷贝的多种方式
实现深拷贝的多种方式简单来说,深拷贝主要是将另一个对象的属性值拷贝过来之后,另一个对象的属性值并不受到影响,因为此时它自己在堆中开辟了自己的内存区域,不受外界干扰。浅拷贝主要拷贝的是对象的引用值,当改变对象的值,另一个对象的值也会发生变化。1.简单深拷贝(一层浅拷贝)①for循环拷贝//只复制第一层的浅拷贝javascriptfunc
Stella981 Stella981
3年前
React之浅拷贝与深拷贝
 最近发现的一个bug让我从react框架角度重新复习了一遍浅拷贝与深拷贝。浅拷贝,就是两个变量都是指向一个地址,改变了一个变量,那另一个变量也随之改变。这就是浅拷贝带来的副作用,两个变量会相互影响到,因为它们指向同一个地址。深拷贝,就是互相独立,指向的是不同的地址,一个变量改变了,另一个变量不会被影响到。react角度:父组件传给
Wesley13 Wesley13
3年前
Java深拷贝和浅拷贝
1.浅复制与深复制概念⑴浅拷贝(浅克隆)   复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。⑵深拷贝(深克隆)   复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制
Stella981 Stella981
3年前
JavaScript的深拷贝和浅拷贝
一、数据类型数据分为基本数据类型(String,Number,Boolean,Null,Undefined,Symbol)和对象数据类型。、1.基本数据类型的特点:直接存储在栈(stack)中的数据2.引用数据类型的特点:存储的是该对象在栈中引用,真实的数据放在堆内存里。引用数据类型在栈中存储了指针,该指针指向堆中该实
Wesley13 Wesley13
3年前
Java 浅拷贝和深拷贝
!(https://oscimg.oschina.net/oscnet/b2f493d478242c24dc57d59ce17ceebb54f.jpg)前言Java中的对象拷贝(ObjectCopy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。举例说明:比如,对象A和对象B都属于类S,具有
Stella981 Stella981
3年前
JavaScript基础心法——深拷贝和浅拷贝
!(https://oscimg.oschina.net/oscnet/c131215a5aaaeb7909d7398688df6ea6dcd.png)浅拷贝和深拷贝都是对于JS中的引用类型而言的,浅拷贝就只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。前言说到深浅拷贝,必须先
小温侯
小温侯
Lv1
写不成书,只记得、相思一点。
文章
3
粉丝
0
获赞
0