手写深浅拷贝

159 阅读2分钟

浅拷贝

什么是浅拷贝

只拷贝基本数据类型,而对象引用的对象依然指向原来的对象。因此如果修改引用数据类型中的数据,会修改到原对象。

代码实现

function shallowCopy(obj){
  //首先判断传入的数据是否为对象或者数组
  if(typeof obj !== 'object')return
  //根据传入的是数组还是对象新建空[]||{}
  let newObj = Array.isArray(obj)?[]:{}
  for(let i in obj){
    if(obj.hasOwnProperty(i)){
      newObj[i] = obj[i];
    }
  }
  return newObj
}
        let arr = [1,2,3,[1,2,3]];
        let newArr = shallowCopy(arr);
        newArr[3][1] = 33;
        console.log(arr)//[1,2,3,[1,33,3]]
        console.log(newArr)//[1,2,3,[1,33,3]]

浅拷贝的其他方式

  • Object.assign()
  • xxx.slice()
  • xxx.concat()

深拷贝

什么是深拷贝

不仅复制对象的基本数据类型,对象中引用的对象也复制。会生成一个全新的对象,修改这个对象不会影响到原来的对象。

深拷贝的代码实现

//深拷贝
function deepCopy(obj){
  if(typeof obj !== 'object')return
  let newObj = Array.isArray(obj)?[]:{};
  for(let i in obj){
    if(obj.hasOwnProperty(i)){
      newObj[i] = typeof(obj[i]) == 'object'?deepCopy(obj[i]):obj[i];
    }
  }
  return newObj
}
        let arr = [1,2,3,[1,2,3]];
        let newArr = deepCopy(arr);
        newArr[3][1] = 33;
        console.log(arr)//[1,2,3,[1,2,3]]
        console.log(newArr)//[1,2,3,[1,33,3]]

深拷贝的其他实现方式

- 先转化为json字符串再转化为对象,JSON.parse(JSON.stringfy(xxx))
- 函数库lodash的CloneDeep

使用JSON进行深拷贝的话会有哪些数据拷贝不到

  • 如果obj中存在时间对象,经过深拷贝会变成字符串
  • 如果obj中有RegExp正则或者Error对象,只能得到空对象
  • 如果obj中有函数,undefined,序列化后会将函数和undefined丢失
  • 如果obj中有NAN,Infinity,-Infinity序列化后的结果会变成null
  • 只能序列化对象的可枚举自身属性,如果obj中的对象是构造函数生成的,则使用JSON进行深拷贝以后会丢失对象的constructor。
  • 如果对象中存在循环引用也无法进行深拷贝。
  • 解决方法:使用lodash库中的深拷贝。

场景

-增删改查,修改数据的时候。