深拷贝和浅拷贝的区别

深拷贝与浅拷贝的区别

1 基本数据类型与引用数据类型

1.1 基本数据类型

存储在栈(stack)中的简单数据段,按值访问的,数据大小确定,内存空间大小可以分配,它们是直接按值存放的。
基本数据类型分为Boolean、Null、Undefined、String、Number、Symbol

1.2 引用数据类型

存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。
引用数据类型也是对象数据类型,分为Object、Array、Function、Date、Math、RegExp

1.3 栈与堆的区别

  • 栈(stack)为自动分配的内存空间,它由系统自动释放。
    1)所有在方法中定义的变量都是放在栈内存中,随着方法的执行结束,这个方法的内存栈也自然销毁 。可以递归调用方法,这样随着栈深度的增加,JVM维持着一条长长的方法调用轨迹,知道内存不够分配,产生栈溢出。
    2)优点:存取速度比堆快,仅次于直接位于CPU中的寄存器,数据可以共享;
    3)缺点:存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。
  • 堆(heap)动态分配的内存,大小也不一定会自动释放。

2 深拷贝与浅拷贝

2.1 浅拷贝

在定义一个对象或数组时,变量存放的往往只是一个地址。当我们使用对象拷贝时,如果属性是对象或数组时,这时候我们传递的也只是一个地址。因此子对象在访问该属性时,会根据地址回溯到父对象指向的堆内存中,即父子对象发生了关联,两者的属性值会指向同一内存空间。
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。

代码示例

var a = {key1:"1", key2:["num1","num1"]}
function Copy(p){
   var c ={};
   for (var i in p){
      c[i]=p[i]
   }    
   return c;
}
var b = Copy(a);

b.key3 = "33333"
console.log(b.key3)//33333
console.log(a.key3);//undefined

b.key2.push("num2")
console.log(b.key2);//num1 num1 num2
console.log(a.key2);//num1 num1 num2

2.2 深拷贝

不希望父子对象之间产生关联,属性值类型是数组和或象时只会传址,用递归来解决这个问题,把父对象中所有属于对象的属性类型都遍历赋给子对象即可。
深拷贝:在计算机中开辟了一块新的内存地址用于存放复制的对象。(对属性中所有引用类型的值,遍历到是基本类型的值为止)

代码示例

var a = {key1:"1", key2:["num1","num1"]}
function Copy(p,c){
  var c =c||{};
  for (var i in p){
   if(typeof p[i]==="object"){
     c[i]=(p[i].constructor ===Array)?[]:{}
     Copy(p[i],c[i]);
   }else{
      c[i]=p[i]
   }
  }    
  return c;
}
var b = {}
b = Copy(a,b); 

b.key2.push("num2");
console.log(b.key2); //num1,num1,num2
console.log(a.key2); //num1,num1  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值