乐趣区

关于javascript:JS的深拷贝和浅拷贝的几种实现方案

深拷贝和浅拷贝

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

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

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

    深拷贝
  • 如果属性都是根本数据类型,那么就是拷贝根本数据类型的值
  • 如果属性外面有援用数据类型 (对象),那么会创立新的对象,将原对象的属性和值拷贝进去,放到新对象外面,并且批改新对象不会对原对象产生影响

浅拷贝的实现计划

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: 应用递归函数进行深拷贝
退出移动版