js浅拷贝解决复杂数据类型赋值相互影响

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

示例:

         在项目表格中点击编辑,将scope.row的数据传过来,this.formEdit = scope.row显示el-dialog将数据给一个新对象formEdit,el-dialog绑定formEdit,此时有个现象,就是el-dialog中修改某一项,改变this.formEdit里的值,页面上的scope.row的数据也会改变。

原因:

         复杂数据类型,对象的原型也是引用类型,对象类型的值单独存放。对象原型的方法和属性放在内存中,通过原型链的方式来指向这个地址;所以对象类型存储的是对象的引用地址;

对象类型在复制的时候,只是将对象的引用复制了,将a对象的引用地址值赋值给了b 

所以在b改变对象属性值的时候,a的引用也发生了改变,它们在内存中获取的都是同一个对象。

解决办法及原理:

       在js中将一个值a赋值给另一个值b,在什么情况下改变了b的值会影响a的值?在知道哪种类型赋值后改变值会影响原对象的情况下该怎么做才不会影响原对象?就是这里需要讨论的问题。想要复制的对象的改变不想影响到原对象,首先是哪种类型赋值后改变赋值后的值会影响到被赋值的值?

let a = 1;
let b = a;
b = 2;
console.log(a) // 1 
let obj = {a: 1} 
let obj2 = obj; 
obj2.a = 2; 
console.log(obj) // {a: 2}

从这里我们可以知道:简单数据类型的number赋值后就算改变赋值后的值也不会影响到其本身,但是对象复制后改变了赋值后的值就会影响到其本身。

原理:

javaScript中的数据类型分为两类,简单数据类型和复杂数据类型; 

  • 1.简单数据类型:包括数值,字符串、布尔值、null、undefined; 
  • 2.复杂数据类型:对象即属性的集合(function、Array、Object);

先了解数据类型在计算机中的存储; 

  • 1.简单数据类型:存储的是对象的原始数据; 
  • 2.复杂数据类型:对象的原型也是引用类型,对象类型的值单独存放。对象原型的方法和属性放在内存中,通过原型链的方式来指向这个地址;所以对象类型存储的是对象的引用地址;对象类型在复制的时候,只是将对象的引用复制了,将a对象的引用地址值赋值给了b ,所以在b改变对象属性值的时候,a的引用也发生了改变,它们在内存中获取的都是同一个对象;

如果想要复制一个复杂数据类型却不想影响原对象,此时就需要用到深拷贝/浅拷贝。

浅拷贝:

       首先由一个数组[1,2,3]或对象{name:'porco', age:1},这样的数组或对象中的值统一不为[数组array]或[对象obj]的只有一层数据结构的简单对象,被称为浅拷贝对象,如果单纯的赋值使用例如let a = [1,2,3],如果改变了a,那么原数组也会相应的被改变,对象也是一样。所以遇到这种情况,想要复制的对象的改变不想影响到原对象,就需要浅拷贝方法:如下

/** * 浅拷贝对象: **/ 
let obj = {a:1,b:2} 
let obj2 = {}; 
/*方法1*/ 
for(let e in obj) {
 obj2[e] = obj[e] 
} 
/*方法2*/ 
Object.keys(obj).forEach(e => { 
  obj2[e] = obj[e] 
}) 
obj2.a = 0; 
console.log(obj2) //{a:0, b:2} 
console.log(obj) //{a:1, b:2} 
/*这里还可以使用两种es6浅拷贝方式*/ 
/*这是直接浅拷贝:*/ 
let obj2 = Object.assign({}, obj); 
/*以及直接使用拓展运算符拷贝*/ 
let obj2 = {...obj} 
/*以上四种方式均可作为浅拷贝对象的方式*/
 /***********************************/ 
/** * 浅拷贝数组: **/ 
let arr = [1,2,3] 
/*第一种浅拷贝数组方式*/ 
let arr2 = arr.slice(); 
/*第二种浅拷贝数组方式*/ 
let arr2 = arr.concat(); 
/*第三种浅拷贝数组方式*/ 
let arr2 = []; 
arr.forEach(e => { 
  arr2.push(e)
 }) 
arr2.[0] = 0; 
console.log(arr2) //[0,2,3] 
console.log(arr) //[1,2,3]

深拷贝:

当对象中的第一层级有一项是数组或对象,浅拷贝失效,例如:let a = [{a:1}]或let a = {a:{aa:1}},这样,使用上面的方法都会失效。这时必须使用深拷贝

  • 1、最简单的办法
let BBB = JSON.parse(JSON.stringify(AAA))

这种方法简单适用于普通场景,但是也会抛弃对象的constructor,不管之前的构造函数什么样,深拷贝后都会变成object.这种方法能正确处理的对象只有 Number, String, Boolean, Array, 并且能用jso格式直接表示的数据结构。

  • 2、一个递归方法:
function deepClone(obj) { 
    let objClone = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj === "object") { 
        for(let key in obj) { 
            if(obj.hasOwnProperty(key)) { 
                if(obj[key] && typeof obj[key] === "object") { 
                    objClone[key] = deepClone(obj[key]); 
                } else { 
                    objClone[key] = obj[key]; 
                } 
            } 
        } 
    } 
    return objClone 
}

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值