JS面试题系列(一)深拷贝、浅拷贝

JS面试题系列(一)深拷贝、浅拷贝

深拷贝浅拷贝是一道常见的面试。

浅拷贝

  1. 直接赋值
let a = {
	age: 1
}
let b = a;
console.log(b) // {age: 1}

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

弊端:对象在赋值的过程中其实是复制了地址,从而导致改变了一方其他也都被改变的情况。

  1. Oject.assign()

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

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

可以看到通过Object.assign() 可以解决直接赋值出现的问题;

  1. 展开运算符 …
let a = {
	age: 1
}
let b = {...a};
a.age = 2; 
console.log(b.age)  // 1

深拷贝

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

let a = {
	age: 1,
	person:{
		tall: 180,
	}
}
let b = {...a}
a.person.tall = 170;
console.log(b.person.tall)

浅拷贝只解决了第一层的问题,如果值中海油对象的话,那么又回到了最开始的话题了,两者享有同样的地址,这种情况下就需要用到深拷贝了。

  1. JSON.parse(JSON.stringify(obj))
let a = {
	age: 1,
	person:{
		tall: 180,
	}
}
let b = JSON.parse(JSON.stringify(a))
a.age = 2;
console.log(b)

弊端:

  • 会忽略undefined
  • 会忽略symbol
  • 不能序列化函数
  • 不能解决循环引用的对象
  • 循环引用,也不能通过该方法实现深拷贝
  • 在遇到函数、 undefined 或者 symbol 的时候,该对象也不能正常的序列化
  1. MessageChannel
// 有undefined + 循环引用
let obj = {
  a: 1,
  b: {
    c: 2,
    d: 3,
  },
  f: undefined
}
obj.c = obj.b;
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c

function deepCopy(obj) {
  return new Promise((resolve) => {
    const {port1, port2} = new MessageChannel();
    port2.onmessage = ev => resolve(ev.data);
    port1.postMessage(obj);
  });
}

deepCopy(obj).then((copy) => {           // 请记住`MessageChannel`是异步的这个前提!
    let copyObj = copy;
    console.log(copyObj, obj)
    console.log(copyObj == obj)
});

但拷贝有函数的对象时,还是会报错,这个时候就要考虑用 lodash 的深拷贝函数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值