JS中的深拷贝与浅拷贝

  刚看完JS中的深浅拷贝,来记录分享一番,一起来开心的掉发吧。

  首先了解深浅拷贝之前来看看JS中的几种数据类型,分别有String、Number、Boolean、undefined、null、Object。es6还多了一种symbol,我们暂且先把他放一边。前面提到的几种数据类型前五种也就是String、Number、Boolean、undefined、null都是属于基本数据类型,而Object则是属于复杂数据类型,比如数组Array,日期date,正则reg等等都是属于Object。

  好了,知道这些以后再让我们来看看堆内存和栈内存。首先基本类型都是存放栈内存中,复杂数据类型存放在堆内存中。因为栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储,基本数据类型就是如此。而堆内存存储的对象类型数据对于大小这方面,一般都是未知的。个人认为,这也是为什么null作为一个object类型的变量却存储在栈内存中的原因。当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

  前面提到的数据类型和堆栈内存你可能会疑惑,我就来看看深浅拷贝知道这些干嘛,其实这都是为了更好的理解深浅拷贝。看下面代码先

var arr = [1,2,3];

var newArr = arr;  //[1,2,3]

newArr.push(4) //[1,2,3,4]

arr //[1,2,3,4]

  我们创建一个数组arr,然后新数组newArr = arr,这个时候两个数组的值相等。可是当我修改新数组newArr时,旧数组arr的值也跟着被修改。那么这是为何?

原因就是上面所说当我们创建arr数组时,arr被分配到了堆内存中,在栈内存留下可以寻找到的指针,也就是说当我们创建新数组newArr时,赋予newArr的是arr在栈中的地址(指针),其实仍与旧数组arr共享同一个内存,所以修改新数组newArr后,旧数组arr也会被修改。ok,接着看下面两行代码

var a = 1;

var b = a; //1

b = 2;

a = 1

这个时候出现的情况跟上面为什么不同,因为上面代码中的a,b只是基本类型,声明后都是保存在栈内存中,值虽然相同,但是两个相互独立,修改互不影响。这样一对比是不是清晰一点了。

总结一下:当基本类型实现浅拷贝,存在栈内存中,那么相互独立,互不影响。

     当复杂类型实现浅拷贝,新对象与旧对象仍然同时指向堆内存的同一属性,互不独立,相互影响。

上面提到的复杂类型的浅拷贝不清不楚,藕断丝连在一些场景就很讨人厌了,这个时候我们引入一个深拷贝的概念,什么是深拷贝,字面上的意思就是相比浅拷贝更深一层的拷贝咯。它可以将复杂类型的数据相互独立出来,互不影响。好了,上最后一段代码实现深浅拷贝

function copy(obj) {
    if(typeof obj == "object") { //判断是否复杂类型
       var result = obj.constructor == Array ? [] : {};//判断数组类型或是object,数组即result=[],object即result={}
        for(let i in obj) {
            result[i] = typeof obj[i] == "object" ? copy(obj[i]) : obj[i]//判断数据每一项是否是object
        }
    } else {
        var result = obj //基本类型直接拷贝
    }
  return result;
}
原文地址:https://www.cnblogs.com/xzhan/p/10636866.html