区分JavaScript中的浅拷贝与深拷贝

        拷贝应该对于大家来说挺熟悉的吧,我们简单的ctrl+C和ctrl+V,复制粘贴,拷贝就是这个意思,将一个目标数据复制一份,形成两个个体。

        我们将一个基本数据类型(数值、字符型)的变量赋值给另一个变量,就可以得到两个值相同的变量,改变其中一个变量的值,不会影响另一个变量的值。

        但是,如果操作的目标是复合数据类型(如数组、对象),则会出现两个变量指向同一个对象的情况,如果改变其中一个对象的成员,另一个对象也会发生改变。

具体示例如下:

代码:

script>
    var p1 ={name:'yan',age:21}
    var p2 =p1;
    p2.name ='long';
    console.log(p1);
    console.log(p2);
    console.log(p1===p2);
</script>

运行结果截图:

在网页中,鼠标右键,单击“检查”,进入控制台查看。

         从运行结果可以看出,在将变量p1赋值给p2后,更改p2的成员,p1的成员也会发生改变。这种情况在JavaScript中称之为“浅拷贝”。可以这么理解,将上述代码中的对象“{name:’long’,age:21}”想象成一个文件夹,该文件夹中保存了name和age两个文件,而变量p1是链接到这个文件夹的快捷方式。在执行“var p2=p1;”操作时,是将快捷方式复制了一份,此时两个快捷方式指向了同个文件夹,而不是对文件夹进行复制操作。

其存在的优点:

        在实际开发中,浅拷贝可以节省内存开销。因为一个对象可以保存大量的数据,其占用的内存会比基本数据类型高。如果没有浅拷贝机制,在将对象作为函数参数传递时,函数内部的实参就会创建对象的副本,多占用一份内存空间,尤其是进行函数嵌套调用或递归操作时,占用空间会越来越多。

        与浅拷贝相对应的就是深拷贝,即真正创建一个对象的副本,也就是我们想象中的“CV”。

代码例子如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>深拷贝</title>
</head>
<body>
<script>
  function deepCopy(obj){
      var o ={};
      for (var k in obj){
          o[k] = (typeof obj[k] === 'object') ? deepCopy(obj[k]) :obj[k];
      }
      return o;
  }
  var p1 ={name:'jim',subject:{name:['Html','CSS']} };
  var p2 =deepCopy(p1);
  p2.subject.name[0] = 'JavaScript';
  console.log(p1.subject.name[0]);
  console.log(p2.subject.name[0]);
  console.log(p1 === p2);
</script>
</body>
</html>

运行结果截图:

在网页中,鼠标右键,单击“检查”,进入控制台查看。

         在上述代码中,var o ={};创建了一个新对象o用来保存成员,在for循环语句中遍历了obj对象的每一个成员,在遍历时,通过“o[k] = obj[k]”实现成员的复制。由于传入的对象obj的成员有可能还是一个对象,所以通过typeof来进行判断,如果typeof检测的类型为object(数组、对象的类型都是object)则递归调用deepCopy()函数,进行完整的复制。

        从结果来看,p1和p2是两个不同的对象,在修改p2的成员后不影响p1的成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序yan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值