谈一谈js中的深拷贝与浅拷贝

**

深浅拷贝

**

let a = {
age: 1
}
let b = a
a.age = 2
console.log(b.age) // 2

从上述例子中我们可以发现,如果给一个变量赋值一个对象,那么两者的值会是同一个引用,其中一方改变,另一方也会相应改变。通常在开发中我们不希望出现这样的问题,我们可以使用浅拷贝来解决这个问题。
**

浅拷贝

**
首先可以通过 Object.assign 来解决这个问题。

let a = {
age: 1
}
let b = Object.assign({}, a)
a.age = 2
console.log(b.age) // 1

当然我们也可以通过展开运算符(…)来解决

let a = {
age: 1
}
let b = {...a}
a.age = 2
console.log(b.age) // 1

通常浅拷贝就能解决大部分问题了,但是当我们遇到如下情况就需要使用到深拷贝了

let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = {...a}
a.jobs.first = 'native'
console.log(b.jobs.first) // native

浅拷贝只解决了第一层的问题,如果接下去的值中还有对象的话,那么就又回到刚开始的话题了,两者享有相同的引用。要解决这个问题,我们需要引入深拷贝。
**

深拷贝

**
这个问题通常可以通过 JSON.parse(JSON.stringify(object)) 来解决。

let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE

但是该方法也是有局限性的:
• 会忽略 undefined
• 不能序列化函数
• 不能解决循环引用的对象

let obj = {
a: 1,
b: {
c: 2,
d: 3,
},
}
obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)

如果你有这么一个循环引用对象,你会发现你不能通过该方法深拷贝
在这里插入图片描述
在遇到函数或者 undefined 的时候,该对象也不能正常的序列化

let a = {
age: undefined,
jobs: function() {},
name: 'yck'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "yck"}

你会发现在上述情况中,该方法会忽略掉函数和 undefined 。但是在通常情况下,复杂数据都是可以序列化的,所以这个函数可以解决大部分问题,并且该函数是内置函数中处理深拷贝性能最快的。当然如果你的数据中含有以上三种情况下,可以使用下面函数进行深拷贝

//递归深复制
        function cloneObject(target,source){ //(新对象,老对象)
            //获取对象下面的所有名字
            var names = Object.getOwnPropertyNames(source);
            for(var i=0;i<names.length;i++){
                //当前名字所对应的值
                console.log(names[i])
                var desc = Object.getOwnPropertyDescriptor(source,names[i]);
                if(typeof(desc.value) === "object" && desc.value === null){
                    var obj;
                    if(Array.isArray(dosc.value)){
                        obj=[];
                    }else{
                        obj={};
                    }
                    Object.defineProperty(target,names[i],{
                        configurable:desc.configurable, //是否可删除
                        enumerable:desc.enumerable, //是否可遍历
                        value:obj,  //值
                        writable:desc.writable //是否可修改
                    })
                    cloneObject(obj,desc.value);
                }else{
                    Object.defineProperty(target,names[i],desc)
                }
            }
        }
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值