ES6中深浅copy

172 阅读3分钟

一、前言

  说到深浅拷贝,必须先提到的是JavaScript的数据类型。JavaScript的数据类型分为基本数据类型和引用数据类型。
  浅拷贝和深拷贝都是对于JS中的引用类型而言的;对于基本数据类型的拷贝,并没有深浅拷贝的区别,我们所说的深浅拷贝都是对于引用数据类型而言的。

二、深浅copy

 深copy:数据在copy完之后两者之间没有任何关系。
 浅copy就是指数据在copy完之后两者之间还存在着关系
 1,数据为数组
  1)展开数据基本数据类型,属于深copy,两者之间不再有任何关系

    let a = [1, 2, 3]
    let b = [...a]
    console.log(b) //[1,2,3]
    b[0] = 12
    console.log(b) //[12,2,3]
    console.log(a) //[1,2,3]

  2)展开数据单层对象,属于浅copy,两者之间仍存在关系

    let obj = {name:"tanni",age:12}
    let arr = [obj,2,3]
    let newArr = [...arr]
    console.log(arr)//[ { name: 'tanni', age: 12 }, 2, 3 ]
    console.log(newArr)//[ { name: 'tanni', age: 12 }, 2, 3 ]  将对象展开
    newArr[0].name="wangcai"

    // 数据如果是对象的话,还会存在关系,属于浅copy
    console.log(arr)//[ { name: 'wangcai', age: 12 }, 2, 3 ]
    console.log(newArr)//[ { name: 'wangcai', age: 12 }, 2, 3 ]

 2,数据为数组,遇到slice方法
  1)展开数据是基本数据类型,属于深copy,两者之间没有关系

    let arr = [1,2,3]
    // slice表示剪切数据,得到一个新的数组,
    // 首参是从哪里开始剪切,第二个参数则是到哪里结束,
    // 不包括此处的数据;只有一个参数那么就剪切直到最后
    let newArr = arr.slice(0)
    newArr[0] = 666
    console.log(arr)//[1,2,3]
    console.log(newArr)// [666,2,3]

  2)展开数据是单层对象,属于浅copy,两者之间存在联系

    let obj = {name:"tanni"}
    let arr = [obj,2,3]
    let newArr = arr.slice(0)
    console.log(newArr)//[ { name: 'tanni' }, 2, 3 ]
    newArr[0].name = "wangcai"
    console.log(arr)//[ { name: 'wangcai' }, 2, 3 ]
    console.log(newArr)//[ { name: 'wangcai' }, 2, 3 ]

 2,数据为对象
  1)数据是单层对象,属于深copy,两者之间没有任何关系

    let obj={name:"tanni",age:12}
    let newObj = {...obj}
    // console.log(newObj)//{name:"tanni",age:12}
    newObj.age = 666
    console.log(obj)//{name:"tanni",age:12}
    console.log(newObj)//{name:"tanni",age:666}

  2)数据是多层对象,属于浅copy,两者存在着联系

    let obj = {name:"tanni",age:{number:12}}
    let newObj = {...obj}
    newObj.age.number = 666
    console.log(obj)//{ name: 'tanni', age: { number: 666 } }
    console.log(newObj)//{ name: 'tanni', age: { number: 666 } }

  3)数据是多层对象,实现深copy,方法如下:
 方法一:利用的是...扩展运算符

    let obj = {name:"tanni",age:{number:12}}
    // console.log(...obj)//需要是可迭代的数据,才可运用...
    let newObj = {...obj,age:{...obj.age}}
    // console.log(newObj)//{ name: 'tanni', age: { number: 12 } }
    newObj.age.number = 666
    console.log(obj)//{ name: 'tanni', age: { number: 12 } }
    console.log(newObj)//{ name: 'tanni', age: { number: 666 } }

 方法二:利用JSON.parse(JSON.stringify(obj))

    let obj = {name:"tani",age:{number:12}}
    let str = JSON.stringify(obj)//将JSON对象转成Json字符串
    // console.log(str)//{"name":"tani","age":{"number":12}}
    let newObj = JSON.parse(str)//解析JSON字符串到对象
    // console.log(newObj)//{ name: 'tani', age: { number: 12 } }
    newObj.age.number = 1233
    console.log(obj)
    console.log(newObj)//{ name: 'tani', age: { number: 1233 } }

缺点:JSON.parse(JSON.stringify(obj))的不足之处
 上述方法会造成数据的丢失,数据必须完全满足json格式才OK!

    let obj = {name:"tanni",age:function(){}}
    let newObj = JSON.parse(JSON.stringify(obj))
    console.log(newObj)//{name:"tanni"}  会导致数据丢失