深拷贝与浅拷贝

221 阅读2分钟

深拷贝与浅拷贝

  1. 一般数据类型存储

 var a = 1
 
 Number String Boolean Symbol null undefined
  1. 引用数据类型

 var obj = {}
​
object function array date/**
 {} 会保存在堆内存中 
 
 ojb 会保存在栈内存中 obj 的指向为 {}  obj ---- > {}
 */

深拷贝 浅拷贝 赋值

  • 浅拷贝:创建一个新对象 拷贝当前对象的原始属性 如果属性是基本类型 拷贝的是基本类型的值 如果是引用类型则拷贝的是引用类型的内存地址 如果其他对象更改了其内存地址 则会影响到另个对象
  • 深拷贝:是从内存中完整拷贝出改对象 然后再内存中新开辟一个空间来存储 拷贝两者之间地址没有关联 更改地址后 不会影响改对象
 var a = 123
 var obj = {}
 var father = {
     name:'zhangs',
     play:['a',{cat:'mao'},4]
 }
 var son  = father
 son.name = 1 
 son.play[0] = 'c'
// log(son , father)  {name:1,play:['c',{cat:'mao'},4]} 
​
​
  • 引用类型的赋值是对象引用

    因为内存地址指向同一个地方 则改变改堆内存数据后 son 和 father 的值都会更改

graph LR;
    栈内存---堆内存;
    son赋值-->obj;
    father赋值-->obj
 
graph LR;
      father浅拷贝-->obj基本数据类型;
     son浅拷贝-->obj1基本数据类型;
graph LR;
    father浅拷贝-->obj引入数据类型;
    son浅拷贝-->obj引入数据类型;

浅拷贝 赋值 深拷贝 区别

  • 赋值:指向的是栈内存的地址 就是指向的栈内存的地址 而不是堆内存的数据 可以理解为两个对象指向了同一个堆内存 这样 无论哪个对象发生改变 都会影响堆内存的数据 而改变另一个对象
  • 浅拷贝:是重新在堆内存中新建一个内存 对对象里面的数据进行递归拷贝 拷贝后的基本数据类型互不影响 拷贝后的引入数据类型 因为指向的都是同一个堆内存,所以会互相影响
  • 深拷贝:从堆内存新开辟一块内存来存放新对象 拷贝前后堆 栈 内存都互不影响
 var father = {
     name:'zhangs',
     play:['a',{cat:'mao'},4]
 }
 
 // 浅拷贝
function copy(obj){
    let obj1 = {}
    for(var k in obj){
        if(obj.hasOwnProperty(k)){
           obj1[k] = obj[k]   
        }
    }
   return obj1  
} 
var son = copy(father)
son.name = 'lis'
son.play[0]= 'c'
//log son father
// { name: 'lis', play: [ 'c', { cat: 'mao' }, 4 ] } 
// { name: 'zhangs', play: [ 'c', { cat: 'mao' }, 4 ] }/*基本数据类型不会相互影响 但是引用数据类型会相互影响 */// 深拷贝
function deepCopy(obj){
    var obj1 = new obj.constructor()
    // 递归需要有出口 
    if(obj === null) return obj
    if (typeof obj !== 'object') return obj
    if(obj instanceof Date) return new Date(obj) 
    if(obj instanceof RegExp) return new RegExp(obj) 
   for(var k in obj){
       if(obj.hasOwnProperty(k)){
          obj1[k] = deepCopy(obj[k])   
       }
   }
  return obj1  
} 
var son = deepCopy(father)
son.name = 'lis'
son.play[0] = 'c'
console.log(son,father)
​
//log { name: 'lis', play: [ 'c', { cat: 'mao' }, 4 ] } 
//    { name: 'zhangs', play: [ 'a', { cat: 'mao' }, 4 ] }
​
​
  • 使用JSON来进行深拷贝

    json.parse() 对于 function date 等不能转换 会导致为空

    var father = {
        name:'zhangs',
        play:['a',{cat:'mao'},4]
    }
    // 深拷贝
    function deepCopy(obj){
      
      return JSON.stringify(obj)  
    } 
    ​
    var son = JSON.parse(deepCopy(father))
    son.name = 'lis'
    son.play[0] = 'c'
    console.log(son,father)
    ​
    //log { name: 'lis', play: [ 'c', { cat: 'mao' }, 4 ] } 
    //    { name: 'zhangs', play: [ 'a', { cat: 'mao' }, 4 ] }
    

    \