35.数据拷贝

106 阅读2分钟

数据拷贝在js中也是重要的一个知识点,数据拷贝分为简单数据类型的拷贝和复杂数据类型的拷贝,复杂数据类型又分为了深拷贝和浅拷贝.

简单数据类型

简单数据类型,string,num, boolean,null,undefine,symbol等这些简单的数据类型我们在复制的时候只需要'='赋值就可以实现拷贝操作.

复杂(引用)数据类型

我们知道在js中复杂数据在内存中是单独储存的,我们用的只是他的内存地址,所有我们直接=赋值的话,只是复制了他的内存地址,所以我们修改也会影响到之前的数据.

浅拷贝

浅拷贝就是拷贝引用数据类型的内存地址,我们常用的主要有以下几种方法.

  • =赋值
  • 数组的slice,contact等方法
  • Object.assign()
  • ...扩展运算法 以上几种方法都是对引用数据类型的浅拷贝,当我们修改是会影响到原数据.

深拷贝

深拷贝是拷贝数据,而不是内存地址,所以我们需要做一个特殊的处理,比如使用JSON对象方法,使用一些库的方法比如lodash,再或者自己封装一些方法.\

  • JSON 我们可以通过JSON.stringify,JSON.parse先将数据转换为JSON格式,再转换回来
let array = [1, 2, 3];
let newArray = JSON.parse(JSON.stringify(array));
console.log(newArray, newArray === array); //[ 1, 2, 3 ] false

但是也有一些问题,有些数据不符合JSON格式的不能转换,比如undefined,symbol,function

let obj = {
  name: 'zs',
  age: 18,
  eat: () => {
    console.log('吃东西');
  },
  sex: undefined,
  girlFriend: null,
  id: Symbol('123')
};

let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj);//{ name: 'zs', age: 18, girlFriend: null }

可以看到我们函数,undefined,symbol已经丢失了

  • _.cloneDeep(value) lodash的深拷贝方法 _.cloneDeep(target) 返回结果值
   let obj = {
      name: 'zs',
      age: 18,
      eat: () => {
        console.log('吃东西');
      },
      sex: undefined,
      girlFriend: null,
      id: Symbol('123')
    };

    var newObject = _.cloneDeep(obj);
    console.log(newObject, obj === newObject);

image.png

  • 自己封装方法 我们自己封装的时候有几个注意项 1判断null的存在
    2.函数的复制
    3.特殊对象,Reg,Date需要重新new一个
    4.注意对象嵌套成环的情况.
function deepClone(origin, hashMap = new WeakMap()) {
  // var a = undefined  a == null // true
  if (origin == undefined || typeof origin !== 'object') {
    return origin;
  }
  if (origin instanceof Date) {
    return new Date(origin);
  }
  if (origin instanceof RegExp) {
    return new RegExp(origin);
  }
  const hashKey = hashMap.get(origin);
  if (hashKey) return hashKey;
  const target = new origin.constructor();
  hashMap.set(origin, target);
  // 剩下的就是[] 和 {} 函数静态不拷贝
  for (const originKey in origin) {
    if (origin.hasOwnProperty(originKey)) {
      target[originKey] = deepClone(origin[originKey], hashMap);
    }
  }
  return target;
}