几个例子理解浅拷贝和深拷贝

时间:2021-10-14 19:53:53

一、内存的堆栈

  1. 基本类型
    存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,当它赋给另一个变量的时候,另一个变量发生改变,原数据不会发生改变:
  var a = 5;
  var b = a;
  b += 1;
  console.log(b)  //6
  console.log(a)  //5

5种基本数据类型有Undefined、Null、Boolean、Number 和 String,它们是直接按值存放的,所以可以直接访问。

  1. 引用类型
    存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况进行特定的分配。当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
  var a = { userName : 'undefined' };
  var b = a;
  b.userName = 'xiaoming';
  console.log(a);  //{userName: "xiaoming"}
  console.log(b);  //{userName: "xiaoming"}

几个例子理解浅拷贝和深拷贝

上面的例子把a的值赋值给b,当b的值发生改变的时候,a的值也会跟随改变,像上面的图解一样,a和b都是指向同一个地址。如果要让b得到一个独立的地址呢?这就涉及到拷贝了。

二、Object.assign

浅拷贝是复制浅层的引用类型,比如复制a = { userName : 'undefined' }这样的对象就是属于浅拷贝,它只有一层,像复制b = { info : { userName : 'undefined' } }这样有嵌套的对象,多层的引用类型,就需要用到深拷贝了。

  • Object.assign()方法可以得到一份浅拷贝的引用类型
  var a = { userName : 'undefined' };
  var b = Object.assign({} , a);
  b.userName = 'xiaoming';
  console.log(a);  //{userName: "undefined"}
  console.log(b);  //{userName: "xiaoming"}

这样,我们就能得到一份浅拷贝内容了,即使是b发生改变,也不会影响到a,它们完全是两个独立的个体,但是此方法不适用深拷贝。

三、展开运算符

  • 利用展开运算符方法也可以得到一份浅拷贝的引用类型:
  var a = { userName : 'undefined' };
  var b = {...a};
  b.userName = 'xiaoming';
  console.log(a);  //{userName: "undefined"}
  console.log(b);  //{userName: "xiaoming"}

这样,我们也能得到一份浅拷贝内容。

四、JSON.parse()&JSON.stringify()

  • 利用JSON下面的parse()方法和stringify()方法可以得到一份深拷贝内容,stringify()方法可以把对象转变成json格式的字符串,再通过parse()方法进行转译成对象来获得一份拷贝的对象(当然浅拷贝也是适用的):
  var a = { info:{userName : 'undefined'}};
  var b = JSON.parse(JSON.stringify(a));
  b.info.userName = 'xiaoming';
  console.log(a);  // { info:{userName : 'undefined'}};
  console.log(b);  // { info:{userName : 'xiaoming'}};

五、for...in&递归(推荐)

  • 这种方法适用于任何引用类型,原理是使用for..in循环,配合递归函数实现深层拷贝 :
        var a = { info:{userName : 'undefined'}};
        var b = copy(a);
        b.info.userName = 'xiaoming'
        function copy(obj){
            var result = {};
            for(var attr in obj){
                if( typeof obj[attr] === 'object' ){
                    result[attr] = copy(obj[attr]);
                }
                else{
                    result[attr] = obj[attr];
                }
            }
            return result;
        }

        console.log(a);   // { info:{userName : 'undefined'}};
        console.log(b);   //{userName: "xiaoming"}

这样,就可以得到一份深拷贝内容了,其原理就是层层拷贝,利用递归的原理,直到最底层不是对象为止,好啦,本次分享就到这里了,如果有什么不正确的地方,请各位不吝赐教,谢谢~