js浅拷贝、深拷贝

浅拷贝

Object.assign()只会拷贝所有属性的值到新的对象中,如果属性值是对象的话,拷贝的是地址,所以并不是深拷贝

let a ={
    age:1
};
let b = Object.assign({},a);
a.ge = 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,
    msg:{
        name:'zhangsan'
    }
}

let b = {...a};
a.msg.name = 'lisi';
console.log(b.msg.name)//lisi

深拷贝

这个问题通常可以用JSON.pare(JSON.stringify(Object)) 来解决

let a ={
    age:1,
    msg:{
        name:'zhangsan'
    }
}

let b = JSON.parse(JSON.stringify(a));
a.msg.name = 'lisi'

console.log(b.msg.name)//zhangsan

但是该方法也是有局限性

  • 会忽略 undefined
  • 会忽略symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
let obj ={
    a:1,
    b:{
        c:2,
        d:3
    }
}

obj.c = obj.a
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或者symbol的时候,该对象也不能正常序列化

let a ={
    age:undefined,
    sex:symbol,
    jobs:function(){},
    name:'zhangsan'
}
let b = JSON.parse(JSON.stringify(a))

console.log(b)//{name:'zhangsan'}

在通常情况下,这个函数可以解决大部分问题

如果你所需拷贝的对象包含内置类型并且不包含函数,可以使用 MessageChannel


function structuralClone(obj) {
  return new Promise(resolve => {
    const { port1, port2 } = new MessageChannel()
    port2.onmessage = ev => resolve(ev.data)
    port1.postMessage(obj)
  })
}
var obj = {
  a: 1,
  b: {
    c: 2
  }
}

obj.b.d = obj.b

// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
const test = async () => {
  const clone = await structuralClone(obj)
  console.log(clone)
}
test()

手写简易版,更推荐使用lodash 的深拷贝函数

function deepClone(obj){
    function isObject(o){
        return (typeof o === 'object' || typeof o == 'function') && o !== null;
    }
    if(!isObject(obj)){
        throw new Errow('非对象')
    }
    let isArray = Array.isArray(obj);
    let newObj = isArray ? [...obj] : {...obj};
    Reflect.ownKeys(newObj).forEach(key=>{
        newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })
    
    return newObj

}

let obj = {
  a: [1, 2, 3],
  b: {
    c: 2,
    d: 3
  }
}
let newObj = deepClone(obj)
newObj.b.c = 1
console.log(obj.b.c) // 2

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值