深拷贝、浅拷贝-日志

 

数据类型

        原始类型(基本数据) : 存在于栈中(Number,String,Blooean)

        对象类型(引用数据): 在栈中存储的是其引用(地址、指针),真实数据存储在堆内存中

引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体,而深拷贝和浅拷贝也是基于Arrayobj这种引用型的。

赋值、浅拷贝、深拷贝的区别

       1、 赋值:一般都想到var i = 12 。没错,这是原始类型的值,所以这是没什么问题,因为它们只存在于栈中。那假如我赋值的是一个Obj或者array呢

var oInfor= {
    name: 'zhangsan',
    age: 25
}

var i = oInfor;
i.name = 'lisi';
i.age = 18

console.log(i.name,i.age)    //   lisi    18

为什么会把我原来的对象给修改了呢,这样如果在大型项目上分分钟会影响到它的资源,严重的话不可运行(Vue的单向数据流还能很好的报错)。原来是在赋值的时候,它不会开辟(创建)新的空间,只会赋值栈内存里面的指针,所以导致大家共用了一块堆内存,那么知道问题了,那咋们就灵活运用下es6的对象方法修改一下:

var oInfor= {
    name: 'zhangsan',
    age: 25
}

var i = Object.assign({},oInfor);    
i.name = 'lisi';
i.age = 18

console.log(oInfor.name,oInfor.age)     //zhangsan   25
console.log(i.name,i.age)    //   lisi    18

但是值得注意的是:Object.assign这个枚举方法是浅拷贝的原理,当有两层引用的时候就会拷贝栈内存里面的指向指针(此问题稍后说浅拷贝的时候说),还有继承属性和不可枚举属性都是不能拷贝的。如果想深入了解可以去MDN查看:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

      2、浅拷贝:它是一个按位拷贝对象。它会创建一个新的对象,把原来对象的属性值精确的进行拷贝过来,如果是基础的数据类型,那拷贝的也就是基础数据类型的值,如果是引用数据类型,那拷贝的就是栈内存的指针地址,因此如果修改这个对象的值也一样会导致原数据给修改,还不明白?那下面通过代码看下:

function copyObj (obj){
    var _oObj = {};
    
    for(var i in obj ){
        _oObj[i] = obj[i]
    }
    return _oObj
}

var oInfor= {
    name: 'zhangsan',
    age: {
        one: 18
    }
}
var oObj = copyObj(oInfor)
oObj.name = 'lisi' 
oObj.age.one = 20


console.log(oInfor)  // zhangsan   20
console.log(oObj )   //   lisi    20

      3、既然有浅那就肯定有深,毕竟马克思基本理论说过事物都是对立的。深拷贝就是进入到多层对象引用中进行拷贝,这个好处就是你修改的所有值都不会改变原来的内容。可以用递归的方式来实现深度克隆的原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝。下面就通过递归代码来了解下内部原理(时间有限就不写了,引用https://juejin.im/post/5b5dcf8351882519790c9a2e):

    //定义检测数据类型的功能函数
    function checkedType(target) {
      return Object.prototype.toString.call(target).slice(8, -1)
    }
    //实现深度克隆---对象/数组
    function clone(target) {
      //判断拷贝的数据类型
      //初始化变量result 成为最终克隆的数据
      let result, targetType = checkedType(target)
      if (targetType === 'Object') {
        result = {}
      } else if (targetType === 'Array') {
        result = []
      } else {
        return target
      }
      //遍历目标数据
      for (let i in target) {
        //获取遍历数据结构的每一项值。
        let value = target[i]
        //判断目标结构里的每一值是否存在对象/数组
        if (checkedType(value) === 'Object' ||
          checkedType(value) === 'Array') { //对象/数组里嵌套了对象/数组
          //继续遍历获取到value值
          result[i] = clone(value)
        } else { //获取到value值是基本的数据类型或者是函数。
          result[i] = value;
        }
      }
      return result
    }

当然,不单单只有递归一种方式,如果想了解的更深入可以去google or baidu下

                                                                                                                                                              

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值