如何实现深拷贝和浅拷贝

173 阅读3分钟

在很多的案例中我们可能需要用到深拷贝或者浅拷贝,接下来我来说说深拷贝和浅拷贝的区别及其用法。

1.浅拷贝的用法

1.Object.assign()

let obj = {
    a: 1,
    b: {
      c: 2,
    },
    d: [3, 4],
};

let obj1=Object.assign(obj)
console.log(obj1);

这里输出的结果跟输出obj的输出结果一样

2.ES6展开运算

let obj2={...obj}

这里是先把obj结构然后外边花括号再合并成对象

3.concat

let obj4=[].concat(obj)[0]

这里因为concat是数组的方法,所以先用[]把obj拼劲进数组[]然后取第一项就是obj

2.深拷贝的用法

1.JSON.parse(JSON.stringify())

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

在这里先是使用转字符串方法转成字符串再使用JSON.parse转为原来对象,这里因为转化为字符串之后就跟原来的对象没有任何的关系了。但是这个方法只支持json能理解的数据格式。

2.自己的方法实现一个

function Copy(obj) {
    let result;
    if (typeof obj == "object") {
      if (Array.isArray(obj)) {
        result = [];
        for (let i = 0; i <= obj.length - 1; i++) {
          result[i] = Copy(obj[i]);
        }
      } else {
        result = {};
        for (let key in obj) {
          result[key] = Copy(obj[key]);
        }
      }
    } else {
      return obj;
    }
    return result;
}

这里我先是声明一个变量result来接收值,第一部先判断传进来的obj是不是复杂数据类型,当是复杂数据类型的时候我有进行数组判断,判断传进来的是不是一个数组,当是数组的时候我把result的值赋值为[]然后循环数组obj,result的每一项就是obj的每一项,但是因为obj的每一项可能又复杂数据类型的值,所以再次调用函数。当不是数组的时候把result赋值成{}利用对象的循环方法for in 进行循环。当不是复杂数据类型的时候直接返回当前值,最后返回result。

3.深拷贝和浅拷贝的区别

let obj2 = { ...obj };
obj.d.push(5)

当使用解构的方法拷贝了obj之后,改变obj里边的复发数据类型的值,obj2也会跟着改变,这就是浅拷贝

 function Copy(obj) {
    let result;
    if (typeof obj == "object") {
      if (Array.isArray(obj)) {
        result = [];
        for (let i = 0; i <= obj.length - 1; i++) {
          result[i] = Copy(obj[i]);
        }
      } else {
        result = {};
        for (let key in obj) {
          result[key] = Copy(obj[key]);
        }
      }
    } else {
      return obj;
    }
    return result;
  }
    let obj6 = Copy(obj);
    obj.d.push(6);
    console.log(obj6);

用这个深拷贝的方法,改变obj的值之后这个深拷贝出来的obj6的值是不会跟着改变的

基本数据类型,拷贝是直接拷贝变量的值,而引用类型拷贝的其实是变量的地址。 而浅拷贝和深拷贝就是在这个基础之上做的区分,如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有重新创建一个新的对象,则认为是浅拷贝; 反之,在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量,则认为是深拷贝。