js深拷贝和浅拷贝怎么实现深拷贝

js变量复制,复杂类型存的是地址值,浅拷贝只是把地址值复制了一份,拷贝对象和原对象指向同一个地址, 一个改变也会影响另外一个

浅拷贝

  1. 对象复制
  2. Object.assign()
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);  // 返回  {a:1, b:2, c:3}
target // {a:1, b:2, c:3}
  1. ...obg 扩展运算符

深拷贝

  1. JSON,parse(JSON.stringify)
    1. 拷贝的对象的值中如果有函数,undefined,symbol则经过JSON.stringify()序列化后的JSON字符串中这个键值对会消失
    1. 无法拷贝不可枚举的属性,无法拷贝对象的原型链
    1. 拷贝Date引用类型会变成字符串
// let date = new Date()
// undefined
// DataTransfer
// ƒ DataTransfer() { [native code] }
// date
// Mon Dec 07 2020 10:48:10 GMT+0800 (中国标准时间)
// JSON.stringify(new Date())
// ""2020-12-07T02:48:58.265Z""
    1. 拷贝RegExp引用类型会变成空对象
    1. 对象中含有NaN、Infinity和-Infinity,则序列化的结果会变成null
    1. 无法拷贝对象的循环应用(即obj[key] = obj)

深拷贝实现

var obj = {
  a: 2,
  b: [1,2,3,{aa: 11, bb:22}],
  c: function () {
    console.log("cccc")
  },
  d: undefined,
  e: 'e',
  f: /^\d+$/
}

// let obj1 = JSON.parse(JSON.stringify(obj))  // 会丢失c的function 和d的undefined 正则({})/日期格式 会改变
// 方法1
function deepClone (obj) {
  let objClone = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {  // 如果是私有属性 不是原型上的才进入
      if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
        deepClone(obj[key])
      } else {
        objClone[key] = obj[key]
      } 
    }
  }
  return objClone
} 
let obj2 = deepClone(obj)
console.log(obj2)

// 方法2
function deepClone2 (obj) {
  //过滤特殊情况
  if (obj === null) return;
  if (typeof obj != 'object') return  obj;
  if (obj instanceof RegExp) {
    return new RegExp(obj)
   }
  // => 不直接创建空对象的目的,克隆的结果和之前保持相同的所属类
  let newObj = new obj.constructor;
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepClone2(obj[key])
    }
  }
  return newObj;
}

let obj3 = deepClone2(obj);
console.log(obj3)

推荐阅读更多精彩内容