JavaScript学习之深拷贝浅拷贝

85 阅读2分钟

浅拷贝

对引用对象的引用,拷贝后的对象发生变化之后原对象也变化,反之也是

深拷贝

深拷贝就是对引用对象的完全拷贝,而不是引用,则改变拷贝后的对象之后原对象不改变,反之也是。

实现深拷贝的方式:

  1. JSON``.parse(JSON.stringify(obj))
  2. 利用递归实现

JSON.parse(JSON.stringify(obj))

JSON.Stringify() 将js值或对象转为json字符串,JSON.parse()将json字符串转为js值或对象

    var obj = {
        a: 10,
        b: 20,
      };
      const newObj = JSON.parse(JSON.stringify(obj));
      console.log(newObj);// {a: 10, b: 20}
      newObj.a = 33;
      console.log(newObj.a);//33
      console.log(obj.a);//10

上面的例子所示,这种方法是可以进行深拷贝的,但是它只能适用于一些简单的情况。比如以下例子就不可以

  var obj = {
        a: 10,
        b: 20,
        say() {
          console.log("hahaha");
        },
      };
      const newObj = JSON.parse(JSON.stringify(obj));
      console.log(newObj);// {a: 10, b: 20}

从这个例子我们可以看到JSON``.parse(JSON.stringify(obj)) 这种方式的深拷贝是不能拷贝对象中的方法,会把对象中的方法给忽略掉。在MDN官方解释JSON.stringify(obj) 在转换过程中会忽略掉 undefinedfunctionsymbol

所以,有些情况这种方式是不行的。

递归方式

递归方式:对每一层的数据实现创建对象然后给对象赋值。

   var obj = {
        a: 10,
        b: 20,
        say() {
          console.log("hahaha");
        },
      };
      var arr = [
        "10",
        {
          a: 10,
        },
        [11],
      ]; 
			function deepCopy(obj) {
        let newObj = obj.constructor === Array ? [] : {};
        for (key in obj) {
          if (obj[key] && typeof obj[key] === "object") {
            newObj[key] = deepCopy(obj[key]);
          } else {
            newObj[key] = obj[key];
          }
        }
        return newObj;
      }
      const newObj = deepCopy(obj);
      newObj.a = 30;
      console.log(newObj);// {a: 30, b: 20, say: ƒ}
      console.log(obj);// {a: 10, b: 20, say: ƒ}
      console.log(deepCopy(arr));// (3) ["10", {…}, Array(1)]

javaScript中的拷贝方法

  1. concat() 连接多个数组,它不会修改已存在的数组的,而是返回一个新数组。但是如果里面的数组是多层的,第一层虽然不会改变原来的,但是深层的对象会改变的。
  2. slice() 数组截取,和concat一样,一层没事,多层不行。
  1. ... 展开运算符,也是对第一层深拷贝,深层浅拷贝(只是引用