• 注册
  • 前端博客 前端博客 关注:0 内容:1116

    JS的深浅复制,原来如此!

  • 查看作者
  • 打赏作者
  • 当前位置: 职业司 > 前端开发 > 前端博客 > 正文
    • 前端博客
    • 本文分享自华为云社区《js的深浅复制,一看就明白》,作者: 鑫2020。

      浅复制的意思

      浅复制是仅仅对数据存放在栈内的引用的复制,没有复制引用指向堆内的内容。多个数据的浅复制,这复制多个引用,这多个引用共同指向堆内的同一个内容。当一个浅复制数据做出修改,即堆内的引用指向的内容发生修改,这时,其他通过引用指向这里的数据也会随着改变。

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = obj;
      objA.a = 'a';
      console.log(obj.a);  // 'a'
      console.log(objA.a);  // 'a'

      深复制的意思

      深复制是指连同堆的内容一块复制,生成一个新的对象。多个深复制将是多个不同的对象,也就有不同的引用,也就指向不同的堆内容。

      使用深复制的原由

      在平常开发中,有时会有数据的传递与接收,当拿到传过来的数据后,难免需要对数据进行加工和改造,为了不破坏原有数据结构,这时就可以使用深复制拷贝数据,然后处理生成的新的数据。深复制也可以防止修改多个引用后引用混乱的问题,减少BUG的产生机会。

      可实现深复制的几种方法

      实现方式一:JSON的序列化与反序列化

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = JSON.parse(JSON.stringify(obj));//JSON的序列化与反序列化
      objA.a = 'a';
      console.log(obj.a);  // 1
      console.log(objA.a);  // 'a'

      虽然JSON的序列化与反序列化可以实现深复制,但有几个缺点需要注意:
      1、date日期对象被转成日期日期字符串
      2、没法访问到原型
      3、复制不了undefined的属性
      4、NAN和无穷被转为NULL

      let d1 = new Date();
      let obj = {
      d1,
      d2: undefined,
      d3:NaN
      }
      let objD = JSON.parse(JSON.stringify(obj));
      console.log(obj)
      console.log(objD)

      实现方式二:Object.assign()

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = Object.assign(obj);
      objA.a = 'a';
      console.log(obj.a);  // 1
      console.log(objA.a);  // 'a'

      虽然Object.assign()可以实现深复制,但对于更深层次的对象引用也是仅仅浅复制。

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = Object.assign(obj);
      objA.c.c1 = 'c1'; //Object.assign()仅仅是一层深复制。
      console.log(obj.c.c1);  // 'c1'
      console.log(objA.c.c1);  // 'c1'

      实现方式三:扩展运算符

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = {...obj};;
      objA.a = 'a';
      console.log(obj.a);  // 1
      console.log(objA.a);  // 'a'

      虽然扩展运算符”…”可以实现深复制,但对于更深层次的对象引用也是仅仅浅复制。

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = {...obj};
      objA.c.c1 = 'c1'; //扩展运算符"..."同Object.assign()一样,仅仅是一层深复制,不能多层深复制。
      console.log(obj.c.c1);  // 'c1'
      console.log(objA.c.c1);  // 'c1'

      实现方式四:使用递归

      想要实现深复制,且实现多层深复制则可以使用递归循环复制。

      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      const ReCopy = function (paramter) {
      let target = null;
      let isObject = paramter.constructor === Object;
      let isArray = paramter.constructor === Array;
      if (isObject || isArray) {
      target = Array.isArray(paramter) ? [] : {};
      for (let i in paramter) {
      target[i] = ReCopy(paramter[i]);
      }
      } else {
      target = paramter;
      }
      return target;
      }
      let objA = ReCopy(obj);
      objA.c.c1 = 'c1';
      console.log(obj.c.c1);  // 10
      console.log(objA.c.c1);  // 'c1'

      ladash深拷贝

      lodash深复制是更专业的深复制方式。

      • 安装lodash
        先初始化,生成package.json文件,然后使用一下命令安装。
      npm i -S lodash
      • 引入lodash
      var _ = require('lodash');
      • 使用lodash
      let obj = {
      a:1,
      b:2,
      c:{
      c1:10,
      c2:20
      }
      }
      let objA = _.cloneDeep(obj);
      objA.c.c1 = 'c1';
      console.log(obj.c.c1);  // 10
      console.log(objA.c.c1);  // 'c1'

      请登录之后再进行评论

      登录

      手机阅读天地(APP)

      • 微信公众号
      • 微信小程序
      • 安卓APP
      手机浏览,惊喜多多
      匿名树洞,说我想说!
      问答悬赏,VIP可见!
      密码可见,回复可见!
      即时聊天、群聊互动!
      宠物孵化,赠送礼物!
      动态像框,专属头衔!
      挑战/抽奖,金币送不停!
      赶紧体会下,不会让你失望!
    • 实时动态
    • 签到
    • 做任务
    • 发表内容
    • 偏好设置
    • 到底部
    • 帖子间隔 侧栏位置:
    • 还没有账号?点这里立即注册