黑马程序员技术交流社区

标题: 易懂js的浅克隆和深克隆原理 [打印本页]

作者: 逆风TO    时间: 2020-5-4 15:42
标题: 易懂js的浅克隆和深克隆原理
本帖最后由 逆风TO 于 2020-5-4 15:47 编辑

什么是克隆

其实js里的克隆跟生活里说的克隆是一样的。有一个本体,克隆出跟本体一摸一样的副体,当本体“受伤”时副体是不会“受伤”的,js的克隆也是如此。
来看下面代码

[JavaScript] 纯文本查看 复制代码
<script>
      var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
      };
      console.log(
        `本体有---${benti.top}、${benti.leg}、${benti.waist}、${benti.hand}`
      );
</script>
想要克隆出一个副体应该怎么做呢?有些人就想到直接将本体赋值给副体
[JavaScript] 纯文本查看 复制代码
<script>
      var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
      };
      var futi = benti;   
      console.log(
        `本体有---${benti.top}、${benti.leg}、${benti.waist}、${benti.hand}`
      );
      console.log(
        `副体有---${futi.top}、${futi.leg}、${futi.waist}、${futi.hand}`
      );
</script>

输出结果

从输出结果来看确实是“克隆”出来一个副体,上面说过克隆出来的副体是不会因为本体“受伤”而“受伤”的,那再看下面代码
[JavaScript] 纯文本查看 复制代码
<script>
      var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
      };
      var futi = benti;
      benti.top = "本体的铁头受伤了"; //本体的头受伤了
      console.log(
        `本体有${benti.top}、${benti.leg}、${benti.waist}、${benti.hand}`
      );
      console.log(
        `副体有${futi.top}、${futi.leg}、${futi.waist}、${futi.hand}`
      );
    </script>

输出结果

按道理来说本体受伤,副体不应该受伤的呀!为什么会这样呢?因为在内存中,对象存储是存在一个地址中的,这样直接赋值给副体,相当于直接把地址值给了副本,并不是克隆一个新的地址值,看下图

所以说这样子的做法并不是克隆。接下来我们要谈谈浅克隆和深克隆

浅克隆
什么是浅克隆
只克隆第一级属性,如果某个属性又是一个内嵌的子对象,不会进入子对象中克隆子对象的内容。

这里用for in 来实现浅克隆,看以下代码
[JavaScript] 纯文本查看 复制代码
<script>
      var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
      };
      //浅克隆
      function clone(oldObj) {
        var newObj = {};
        for (var key in oldObj) {
          newObj[key] = oldObj[key];
        }
        return newObj;
      }
      var futi = clone(benti);
      benti.top = "本体的铁头受伤了"; //本体的头受伤了
      console.log(
        `本体有---${benti.top}、${benti.leg}、${benti.waist}、${benti.hand}`
      );
      console.log(
        `副体有---${futi.top}、${futi.leg}、${futi.waist}、${futi.hand}`
      );
</script>
输出结果

克隆出来的副体与本体没有联系,即使改变本体的属性值,副体也不会被被改变这就是浅克隆,看下图的解释

这样就达到了基本的浅克隆,但是这个浅克隆有些小问题需要注意,如果有些人想向克隆函数传一个null,数字,字符串,数组呢?不能都返回一个对象给别人吧!我们是想别人想克隆什么类型的就返回什么类型的给别人。那可以改一改上面的代码
[Java] 纯文本查看 复制代码
<script>
      var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
      };
      //浅克隆
      function clone(oldObj) {
        //如果传进来的参数是null,那就返回一个null
        if (oldObj == null) {
          return null; //直接退出
        }
        //如果传进来的是原始类型值,就返回原始类型值
        if (typeof oldObj != "object") {
          return oldObj; //直接退出
        } else {
          var newObj = Array.isArray(oldObj) ? [] : {}; //不要直接创建对象,先使用三目运算符判断是创建数组还是对象
          for (var key in oldObj) {
            newObj[key] = oldObj[key];
          }
          return newObj; //返回新对象或数组
        }
      }
      //克隆一个对象
      var futi = clone(benti);
      benti.top = "本体的铁头受伤了"; //本体的头受伤了
      console.log(
        `本体有---${benti.top}、${benti.leg}、${benti.waist}、${benti.hand}`
      );
      console.log(
        `副体有---${futi.top}、${futi.leg}、${futi.waist}、${futi.hand}`
      );

      //参数为null
      var boor = clone(null);
      console.log(boor);

      //参数为数字,字符串
      var number = clone(12);
      var string = clone("string");
      console.log(number);
      console.log(string);

      //参数为数组
      var arr = clone([1, 2, 3, 4, 5]);
      console.log(arr);
    </script>

输出结果

这样浅克隆就实现了。接下来看看什么是深克隆吧,深克隆跟浅克隆有什么区别呢?

深克隆什么是深克隆

既可以克隆第一级属性,如果某个属性又是一个内嵌的子对象,深克隆会进入子对象中,继续克隆内嵌子对象及其内容。

什么是内嵌的子对象呢?看下面的代码

[Java] 纯文本查看 复制代码
var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
        chuanzhe:{
                        yifu:"adds",
                        xiezi:"AJ",
                        kuzi:"boshilong"
                }
};

对象benti中的chuanzhe就是内嵌的子对象,如果用浅克隆的方式克隆出来的副体是有问题的,因为对象存储是存在一个地址中,所以浅克隆是无法克隆内嵌的子对象,那深克隆是怎么实现的呢?是利用递归的思想来解决这个问题的,
看下面的代码

[Java] 纯文本查看 复制代码
<script>
      var benti = {
        top: "铁头",
        leg: "大长腿",
        waist: "细腰",
        hand: "小手",
        chuanzhe: {
          yifu: "adds",
          xiezi: "AJ",
          kuzi: "boshilong",
        },
      };
      //深克隆
      function clone(oldObj) {
        //如果传进来的参数是null,那就返回一个null
        if (oldObj == null) {
          return null; //直接退出
        }
        //如果传进来的是原始类型值,就返回原始类型值
        if (typeof oldObj != "object") {
          return oldObj; //直接退出
        } else {
          var newObj = Array.isArray(oldObj) ? [] : {}; //不要直接创建对象,先使用三目运算符判断是创建数组还是对象
          for (var key in oldObj) {
            newObj[key] = clone(oldObj[key]); //如果属性有内嵌子对象就再次调用克隆函数   递归的思想
          }
          return newObj; //返回新对象或数组
        }
      }
      //克隆一个对象
      var futi = clone(benti);
      benti.top = "本体的铁头受伤了"; //本体的头受伤了
      console.log(benti);
      console.log(futi);

      //参数为null
      var boor = clone(null);
      console.log(boor);

      //参数为数字,字符串
      var number = clone(12);
      var string = clone("string");
      console.log(number);
      console.log(string);

      //参数为数组
      var arr = clone([1, 2, 3, 4, 5]);
      console.log(arr);
    </script>

输出结果

这样就实现了深克隆了,最主要的还是这句代码newObj[key] = clone(oldObj[key]);利用了递归的思想,这里就不做过多的介绍了。浅克隆和深克隆就介绍到这里啦!说得不好的,请多多指教。

转自CSDN




作者: 咨询部王丹    时间: 2020-5-18 14:41
感谢分析,
作者: 小公举    时间: 2020-5-18 14:44
克隆看着还挺难的,加油吧,谢谢楼主分享
作者: hello!!!    时间: 2020-5-18 15:05

作者: sdjadyhm    时间: 2020-5-18 15:10
66666666666666
作者: 霍尔    时间: 2020-5-18 15:14
66666666666666666
作者: 耙丫丫    时间: 2020-5-18 15:22
66666666666666666666
作者: 孙丽    时间: 2020-5-18 15:25
66666666666666666
作者: 举个栗子    时间: 2020-5-18 15:33
666666666666666666666666666666
作者: 我爱我1022    时间: 2020-5-18 15:34

作者: 半个程序员    时间: 2020-5-18 15:39
你只管去努力,剩下的交给天意
作者: 你不爱我    时间: 2020-5-18 15:45
加油                           
作者: 我爱我1022    时间: 2020-5-18 15:52

作者: manyihang    时间: 2020-5-18 17:12
6666666666666666666
作者: 逆风TO    时间: 2020-5-18 17:34
你只管去努力,剩下的交给天意。
作者: 大安    时间: 2020-5-18 17:41
感谢分享!
作者: jsnoob    时间: 2020-5-18 23:02
加油加油加油!!!
作者: yujq    时间: 2020-5-19 11:46
6666666666666666666666666
作者: zplxwl    时间: 2020-5-19 15:30
666666666666666666
作者: 1467584    时间: 2020-5-20 09:57
66666666666666666666666666666666

作者: 黑马程序员啊    时间: 2020-5-20 10:30
6666666666666666666666666
作者: 王微    时间: 2020-5-20 11:43

作者: 殷凯老师    时间: 2020-5-20 17:46
你只管去努力,剩下的交给天意
作者: 零度☆黎明    时间: 2020-5-20 23:05
不错, 不错 .................. ..................
作者: 素问    时间: 2020-5-21 00:29
感谢分享,继续加油~~~!!!!
作者: lvxinvip    时间: 2020-5-21 11:02

作者: daoqin    时间: 2020-5-21 11:28
你开心就好喽
作者: hongping    时间: 2020-5-21 15:23
你开心就好啊
作者: hongping    时间: 2020-5-21 15:23
你开心就好啊
作者: zhaosongzhi    时间: 2020-5-21 17:05
6666666666666666666666666666666666
作者: 大智叔叔    时间: 2020-5-21 17:06

加油加油加油!!!
作者: 王锦    时间: 2020-5-21 17:10
66666666666666666666666666666666
作者: 哦嗨呦    时间: 2020-5-21 17:57
好人一生平安
作者: lzq123    时间: 2020-5-21 20:30
666666666666666666
作者: 竹竹竹竹    时间: 2020-5-22 10:12
6666666666666666666666
作者: 影@子~    时间: 2020-5-22 10:13

作者: json0314    时间: 2020-5-22 21:00
6666666666666666
作者: mydorling11    时间: 2020-5-23 18:50
yum install net-tools
作者: 逆风TO    时间: 2020-5-27 12:32
咨询部王丹 发表于 2020-5-18 14:41
感谢分析,

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
zplxwl 发表于 2020-5-19 15:30
666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
1467584 发表于 2020-5-20 09:57
66666666666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
yujq 发表于 2020-5-19 11:46
6666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
zplxwl 发表于 2020-5-19 15:30
666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
逆风TO 发表于 2020-5-18 17:34
你只管去努力,剩下的交给天意。

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
yujq 发表于 2020-5-19 11:46
6666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
zplxwl 发表于 2020-5-19 15:30
666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
1467584 发表于 2020-5-20 09:57
66666666666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:32
逆风TO 发表于 2020-5-27 12:32
打卡签到

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
zplxwl 发表于 2020-5-19 15:30
666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
1467584 发表于 2020-5-20 09:57
66666666666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
yujq 发表于 2020-5-19 11:46
6666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
yujq 发表于 2020-5-19 11:46
6666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
zplxwl 发表于 2020-5-19 15:30
666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
逆风TO 发表于 2020-5-27 12:32
打卡签到

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
manyihang 发表于 2020-5-18 17:12
6666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
逆风TO 发表于 2020-5-27 12:32
打卡签到

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
大安 发表于 2020-5-18 17:41
感谢分享!

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
jsnoob 发表于 2020-5-18 23:02
加油加油加油!!!

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
我爱我1022 发表于 2020-5-18 15:52

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
耙丫丫 发表于 2020-5-18 15:22
66666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:33
大安 发表于 2020-5-18 17:41
感谢分享!

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:34
大安 发表于 2020-5-18 17:41
感谢分享!

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:34
jsnoob 发表于 2020-5-18 23:02
加油加油加油!!!

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:35
yujq 发表于 2020-5-19 11:46
6666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:35
manyihang 发表于 2020-5-18 17:12
6666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:35
jsnoob 发表于 2020-5-18 23:02
加油加油加油!!!

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:36
yujq 发表于 2020-5-19 11:46
6666666666666666666666666

打卡签到
作者: 逆风TO    时间: 2020-5-27 12:36
我爱我1022 发表于 2020-5-18 15:34


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:36
逆风TO 发表于 2020-5-27 12:35
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
逆风TO 发表于 2020-5-27 12:33
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
manyihang 发表于 2020-5-18 17:12
6666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
大安 发表于 2020-5-18 17:41
感谢分享!


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
耙丫丫 发表于 2020-5-18 15:22
66666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
hello!!! 发表于 2020-5-18 15:05


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
sdjadyhm 发表于 2020-5-18 15:10
66666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
逆风TO 发表于 2020-5-27 12:33
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
逆风TO 发表于 2020-5-27 12:33
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
黑马程序员啊 发表于 2020-5-20 10:30
6666666666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
影@子~ 发表于 2020-5-22 10:13


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
zhaosongzhi 发表于 2020-5-21 17:05
6666666666666666666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
lzq123 发表于 2020-5-21 20:30
666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:37
零度☆黎明 发表于 2020-5-20 23:05
不错, 不错 .................. ..................


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
王微 发表于 2020-5-20 11:43


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
零度☆黎明 发表于 2020-5-20 23:05
不错, 不错 .................. ..................


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
零度☆黎明 发表于 2020-5-20 23:05
不错, 不错 .................. ..................


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
王微 发表于 2020-5-20 11:43


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
零度☆黎明 发表于 2020-5-20 23:05
不错, 不错 .................. ..................


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
王微 发表于 2020-5-20 11:43


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:38
零度☆黎明 发表于 2020-5-20 23:05
不错, 不错 .................. ..................


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:39
王微 发表于 2020-5-20 11:43


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:39
零度☆黎明 发表于 2020-5-20 23:05
不错, 不错 .................. ..................


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
hongping 发表于 2020-5-21 15:23
你开心就好啊


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
影@子~ 发表于 2020-5-22 10:13


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
竹竹竹竹 发表于 2020-5-22 10:12
6666666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
影@子~ 发表于 2020-5-22 10:13


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
逆风TO 发表于 2020-5-27 12:32
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
逆风TO 发表于 2020-5-27 12:33
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
逆风TO 发表于 2020-5-27 12:33
打卡签到


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
黑马程序员啊 发表于 2020-5-20 10:30
6666666666666666666666666


你只管去努力,剩下的交给天意
作者: 逆风TO    时间: 2020-5-27 12:40
mydorling11 发表于 2020-5-23 18:50
yum install net-tools


你只管去努力,剩下的交给天意




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2