zoukankan      html  css  js  c++  java
  • js深拷贝与浅拷贝

    老规矩先出一道题目,大家猜猜打印的结果是什么,然后我们一起探讨背后的原因。

    var a=[1,2,3]
    var b=a;
    var c=[6,7,8]
    b=c
    b[0]=9
    a=c
    console.log(a)
    console.log(b)
    console.log(c)
    

    先分析题目,我们会看到b首先对a进行了一次复制,接下来,b又复制了c,
    最后b又改变其中的值。最后打印出a,b,c看看它们的结果有没有什么关联。
    第一步:了解栈(stack)堆(heap)的概念,看看我们的a,b,c存在哪里。
    stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小不定也不会自动释放。

    第二步:存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。
    当b=a时,b这个时候和a指向的是同样的地址,即此刻b=[1,2,3]

    第三步:当堆中出现c的值,并且b=c,这个时候就是b复制c的值,b和c指向同一个地址。此时b的值为[6,7,8]

    第四步:当b的值改变,b[0]=9,此时堆中的值为[9,7,8],此时c的值也为[9,7,8]

    第五步:a复制c,此时a和b和c指向同一个地址。我们也会发现一个问题,那就是原来a中的值似乎还是存在堆中,
    系统无法对它回收,但是我们却不知道通过什么方式找到它,但是它又占用了堆中的内存,这个就是内存泄露。

    上面的就是一个典型的浅拷贝实现过程,拷贝对象里面的属性改变会影响原对象。那什么是深拷贝呢?深拷贝就是
    拷贝对象里面的属性改变不会影响原对象的属性。
    那如何实现一个深拷贝呢?

    var array=[1,2,3]
    function copy(array){
      let newArray=[]
      for(let item of array){
        newArray.push(item)
      }
      return newArray
    }
    var copyArray=copy(array)
    copyArray[0]=100
    console.log(array)
    console.log(copyArray)
    

    第一步:

    第二步:newArray会复制array中的值,不过此时newArray中的值和array的值不在同一个堆中

    第三步:newArray中的值改变了,但是array中的值不会改变。

    同理我们可以实现对象的深拷贝

    var newObject={}
    var obj={
      name:'a',
      b:'student'
    }
    function copy(obj){
      for(let item in obj){
        newObject[item]=obj[item]
      }
      return newObject
    }
    var copyObj=copy(obj)
    copyObj.name='b'
    console.log(obj);//{name:'a',b:'student'}
    console.log(copyObj)//{name:'b',b:'student'}
    

    如果实现一个针对数组和对象的深拷贝是如何实现的呢?

    function deepClone(s,t){
      var t={}||[]
      for(var i in s){
        if(typeof s[i]==='object'){
          t[i]=(s[i].constructor===Array)?[]:{}
          deepClone(s[i],t[i])
        }else{
          t[i]=s[i]
        }
      }
      return t
    }
    a.name={a:'aa'}
    var b={}
    b=deepClone(a,b)
    b.name={a:'bb'}
    console.log(a.name)
    console.log(b.name)
    

    如果不是单独针对数组或对象,而是能够通过数组对象和其他复杂的JSON形式的对象,我们怎么实现深拷贝呢?

    var array=[
      {name:1},
      {name:2},
      {name:3}
    ]
    var copyArray=JSON.parse(JSON.stringify(array))
    copyArray[0].name=100
    console.log('aa',array)
    console.log('bb',copyArray)
    
  • 相关阅读:
    LG4377 「USACO2018OPEN」Talent Show 分数规划+背包
    LG4111/LOJ2122 「HEOI2015」小Z的房间 矩阵树定理
    LG5104 红包发红包 概率与期望
    LG2375/LOJ2246 「NOI2014」动物园 KMP改造
    LG4824 「USACO2015FEB」(Silver)Censoring KMP+栈
    20191004 「HZOJ NOIP2019 Round #9」20191004模拟
    LG5357 「模板」AC自动机(二次加强版) AC自动机+fail树
    LG3812 「模板」线性基 线性基
    数据结构
    git
  • 原文地址:https://www.cnblogs.com/smart-girl/p/10051764.html
Copyright © 2011-2022 走看看