浅拷贝、深拷贝及循环引用

测试数据

let obj = {
    a: 1,
    b: 'b',
    c: null,
    d: undefined,
    e: { a: { b: 1 } },
    f: [1, 2],
    g: function () { console.log(1) },
    h: /cc/ig,
    i: new Date(),
}

浅拷贝

浅拷贝:创建一个对象,复制属性。其中引用类型的属性复制的为地址。

// 方式1
// 实现浅拷贝,并追加{d:3}
let obj2 = Object.assign({}, obi, { d: 3 })

// 方式2
// 展开运算符
let obj3 = {...obj1}

深拷贝

深拷贝:复制整个对象,其中引用类型的属性复制的为值,拷贝后的两个对象是两个独立的个体

简易深拷贝:

  1. 数组、普通对象{}、基本数据类型
  2. 不考虑循环引用
// 判断是否是引用类型
function isObject(val) {
  return val !== null && (typeof val === 'object' || typeof val === 'function')
}

function deepClone1(source) {
  if (!isObject(source)) {
    return source
  }

  let target = Array.isArray(source) ? [] : {}
  for (const key in source) {
    if (Object.hasOwnProperty.call(source, key)) {
      target[key] = deepClone1(source[key])
    }
  }

  return target
}

JSON方式实现简易深拷贝

JSON.parse( JSON.stringify(obj) )
  • 不能拷贝函数、正则、 日期等

完整深拷贝

  1. 需要考虑函数、正则、日期、set、map、Symbol
  2. 需要考虑循环引用问题
// 判断是否是引用类型
function isObject(val) {
    return val !== null && (typeof val === 'object' || typeof val === 'function')
}

function deepClone(source, map = new WeakMap()) {

  // Date类型
  if (source instanceof Date) {
    return new Date(source)
  }

  // 正则
  if (source instanceof RegExp) {
    return new RegExp(source)
  }

  // source为基本数据类型
  // number string boolean null undefined Symbol
  if (!isObject(source)) {
    return source;
  }

  // source函数类型
  if(typeof source === 'function'){
    return source
  }

  if (map.has(source)) {
    return map.get(source)
  }
  // source为引用类型
  const target = Array.isArray(source) ? [] : {};
  map.set(source, target)

  for (const key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      target[key] = deepClone(source[key], map);
    }
  }
  return target;
}


// 循环引用问题
obj._self = obj

let obj_copy = deepClone(obj)
console.log(obj);
console.log(obj_copy);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值