wangzhenggui/blog

javaScript经典系列之浅拷贝与深拷贝

Opened this issue · 0 comments

前言

关于深拷贝和浅拷贝的问题一直都是面试题中比较容易问的问题,这一节,我们就来深入的了解下它!

浅拷贝

创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

使用场景
1、使用Object.assign({},object)来clone一个对象

let obj = {
  a: 'a',
  b: {
    c: 'c'
  }
}
let cloneObj = Object.assign({},obj)
console.log(obj)  // "{"a":"a","b":{"c":"c"}}"
console.log(cloneObj )  // "{"a":"a","b":{"c":"c"}}"

// 修改obj对象的值类型,我们发现俩个对象互不影响
obj.a = 'a1';
console.log(obj)  // "{"a":"a1","b":{"c":"c"}}"
console.log(cloneObj )  // "{"a":"a","b":{"c":"c"}}"

// 修改obj对象的引用类型值, 俩个对象的值都会变化
obj.b.c = 'c1';
console.log(obj)  // "{"a":"a1","b":{"c":"c1"}}"
console.log(cloneObj )  // "{"a":"a","b":{"c":"c1"}}"

2、拷贝数组类型的时候,可以使用concat(),或者slice()函数
3、ES6中的扩展运算符可以实现浅拷贝

let obj = {
  a: 'a',
  b: {
    c: 'c'
  }
}
let cloneObj = {...obj}
console.log(obj)  // "{"a":"a","b":{"c":"c"}}"
console.log(cloneObj )  // "{"a":"a","b":{"c":"c"}}"
// 修改obj对象的值类型,我们发现俩个对象互不影响
obj.a = 'a1';
console.log(obj)  // "{"a":"a1","b":{"c":"c"}}"
console.log(cloneObj )  // "{"a":"a","b":{"c":"c"}}"
// 修改obj对象的引用类型值, 俩个对象的值都会变化
obj.b.c = 'c1';
console.log(obj)  // "{"a":"a1","b":{"c":"c1"}}"
console.log(cloneObj )  // "{"a":"a","b":{"c":"c1"}}"

深拷贝

深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。拷贝前后两个对象互不影响。

使用场景
1、JSON.parse(JSON.stringify(obj)),通过JSON的API将对象序列化之后在转化为对象实现复制一个对象,但是这个方法会存在几个问题

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
  • 不能正确处理new Date()
  • 不能处理正则

2、自己实现深拷贝

function cloneDeep(source) {
  // 是否是对象类型
  if (typeof source !== 'object') {
    return source
  }
  let target = Array.isArray(source) ? [] : {}  //判断是数组还是对象
  for (let key in source) {
    if (source.hasOwnProperty(key)) { // 过滤原型上的属性
      target[key] = typeof source[key] === 'object' ? cloneDeep(source[key]) : source[key] // 如果属性值是对象,递归调用
    }
  }
  return target
}

var obj = {
  name: 'muyiy',
  book: { title: 'You Don\'t Know JS', price: '45' },
  a1: undefined,
  a2: {},
  a3: 123
}

var cloneObj = cloneDeep(obj);

深拷贝与浅拷贝

https://github.com/yygmind/blog/issues/29

https://www.jianshu.com/p/0723efc1e6f6?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation