浅拷贝与深拷贝

首先,JS的浅拷贝和深拷贝只是针对于引用数据类型而言

  • 基本数据类型:Boolean、Number、String、undefined、Null、Symbol (ES6新增,表示独一无二的值)
  • 引用数据类型:Object、Array、Function

浅拷贝:
概念:浅拷贝只是复制指向某个对象的指针,而不复制对象本身,新旧对象其实还是同一个对象。修改时原对象也会受到影响。
深拷贝:
概念:深拷贝就是在拷贝数据的时候,将数据的所有引用结构都拷贝一份。简单的说就是,在内存中存在两个数据结构完全相同又相互独立的数据,将引用型类型进行复制,而不是只复制其引用关系。修改时原对象不再受到任何影响。

看一个非常典型的例子:

// 基本数据类型赋值
var a = 'aaa';
var b = a;
console.log(a);  // 'aaa'
console.log(b);  // 'aaa'
b = 'bbb';
console.log(a);  // 'aaa'
console.log(b);  // 'bbb'

// 引用数据类型赋值
var a = {    name: '张三'};
var b = a;
console.log(a);  // {name: "张三"}
console.log(b);  // {name: "张三"}
b.name = '李四';
b.age = 18;
console.log(a);  // {name: "李四", age: 18}
console.log(b);  // {name: "李四", age: 18}

下面的是浅拷贝,上面的可以“理解”为深拷贝。

浅拷贝方法

  • 利用 = 赋值操作符实现浅拷贝。
  • 使用 slice、concat是数组的浅拷贝。
  • 对象浅拷贝 - Object.assign()。
  • 对象浅拷贝 - 扩展运算符

深拷贝方法

  • 利用 JSON 对象中的 parse 和 stringify—如果对象某个属性值是函数的话,这个函数的值不能被深拷贝

  • 利用递归来实现每一层都重新创建对象并赋值。

  • lodash

1.对于JSON.parse( JSON.stringify() ) 序列化和反序列:
先将需要拷贝的对象进行JSON字符串化,然后再pase解析出来,赋给另一个变量,实现深拷贝。
2.对于Object.assign(target, source1, source2)
es6新增的方法,可用于对象合并,将源对象的所有可枚举属性,复制到目标对象上。
3.迭代递归方法

function deepCopy(data) {
      if(typeof data !== 'object' || data === null){
            throw new TypeError('传入参数不是对象')
        }
      let newData = {};
      const dataKeys = Object.keys(data);
      dataKeys.forEach(value => {
         const currentDataValue = data[value];
         // 基本数据类型的值和函数直接赋值拷贝 
         if (typeof currentDataValue !== "object" || currentDataValue === null) {
              newData[value] = currentDataValue;
          } else if (Array.isArray(currentDataValue)) {
             // 实现数组的深拷贝
            newData[value] = [...currentDataValue];
          } else if (currentDataValue instanceof Set) {
             // 实现set数据的深拷贝
             newData[value] = new Set([...currentDataValue]);
          } else if (currentDataValue instanceof Map) {
             // 实现map数据的深拷贝
             newData[value] = new Map([...currentDataValue]);
          } else { 
             // 普通对象则递归赋值
             newData[value] = deepCopy(currentDataValue);
          } 
       }); 
      return newData;
  }

(解决闭环问题)

function deepCopy(data, hash = new WeakMap()) {
      if(typeof data !== 'object' || data === null){
            throw new TypeError('传入参数不是对象')
        }
      // 判断传入的待拷贝对象的引用是否存在于hash中
      if(hash.has(data)) {
            return hash.get(data)
        }
      let newData = {};
      const dataKeys = Object.keys(data);
      dataKeys.forEach(value => {
         const currentDataValue = data[value];
         // 基本数据类型的值和函数直接赋值拷贝 
         if (typeof currentDataValue !== "object" || currentDataValue === null) {
              newData[value] = currentDataValue;
          } else if (Array.isArray(currentDataValue)) {
             // 实现数组的深拷贝
            newData[value] = [...currentDataValue];
          } else if (currentDataValue instanceof Set) {
             // 实现set数据的深拷贝
             newData[value] = new Set([...currentDataValue]);
          } else if (currentDataValue instanceof Map) {
             // 实现map数据的深拷贝
             newData[value] = new Map([...currentDataValue]);
          } else { 
             // 将这个待拷贝对象的引用存于hash中
             hash.set(data,data)
             // 普通对象则递归赋值
             newData[value] = deepCopy(currentDataValue, hash);
          } 
       }); 
      return newData;
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值