浅拷贝与深拷贝

128 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

为什么要进行拷贝?

var a = {
    a:1
}

var b = a
b.a = 2

当我们通过b.a=2来修改a值时发现,a对象里面的值受到了影响,拷贝就是想要让这两个对象有独立的引用地址空间。

浅拷贝与深拷贝的区别

浅拷贝:实际就是将对象进行一层赋值,深层次的引用地址还是一样,原数据和拷贝后的数据会互相影响 深拷贝:是将对象的每一层进行拷贝,原数据和拷贝后的数据不会互相影响

浅拷贝的实现方式

1.es3方式遍历循环

function simpleClone(obj) {
    let result = {}
    for(i in obj) {
      result[i] = obj[i]
    }
    return result
}

2.es6方式Object.assign()

 var obj1 = {
    a:1,
    b:2,
    c:3,
    d:{
      e:4,
      f:{
        g:5
      }
    }
  }
  

var obj2 = Object.assign({},obj1)

obj2.d.e = 5当执行完这行代码后发现

QQ截图20220609164955.jpg 拷贝的内容修改影响到了原内容,此时Object.assign()方法属于浅拷贝

3.es6方式...扩展运算符

 var obj1 = {
    a:1,
    b:2,
    c:3,
    d:{
      e:4,
      f:{
        g:5
      }
    }
  }
  
  var obj3 = {...obj1}

尝试修改深层的赋值,发现原内容受到影响,故是浅拷贝。

深拷贝的实现方式

1.基础递归

function deepClone(obj) {
  let cloneObj = {}
  for(key in obj) {
    if(typeof obj[key] === 'object' && obj[key] !== null) {
      cloneObj[key] = deepClone(obj[key])
    }else {
      cloneObj[key] = obj[key]
    } 
  }
  return cloneObj
}

2.处理循环引用

let obj = {}
obj.a = obj 

此时会出现一个问题,就是出现递归爆栈。 利用map去将已经拷贝对象存起来,去校验一下当前对象是否在map中。

function isObject(x) { 
  return Object.prototype.toString.call(x) === '[object Object]'; 
}

function deepClone(obj, hash = new Map()) { 
  if (!isObject(obj)) 
  return obj; 
  if (hash.has(obj)) return hash.get(obj); 
  var target = Array.isArray(obj) ? [] : {};   
  hash.set(obj, target);  
  for(var key in obj) { 
    if (obj.hasOwnProperty(key)) { 
      if (isObject(obj[key])) { 
        target[key] = cloneDeep(obj[key], hash);
      } else { 
        target[key] = obj[key]; }
      } 
  }

  return target;
}

3.es6中JSON.parse(JSON.stringify())

let obj = {
  a:1,
  b:2,
  c:3,
  d:{
    e:4,
    f:{
      g:5
    }
  }
}

let cloneObj2 = JSON.parse(JSON.stringify(obj))