一. 简介

简短版:引用,如果对对象的操作不想改变原对象的话可以用深拷贝。

深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。
浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。
深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。

二. 扩展问题

  • 解构赋值是深拷贝还是浅拷贝?实际上,无论是使用扩展运算符(…)还是解构赋值,对于引用类型都是浅拷贝。
  • **Object.assign()** 是深拷贝还是浅拷贝? 浅拷贝,返回目标对象。

三. 如何实现深浅拷贝

以下实现参考: https://juejin.cn/post/6947249325994934302

1. 浅拷贝

  1. // 对 obj 进行浅拷贝
  2. function shallowCopy(obj) {
  3. if (typeof obj === 'object' && obj !== null) {
  4. let copy = Array.isArray(obj) ? [] : {};
  5. // 遍历原对象 obj,将第一层属性赋值给新对象
  6. for (var p in obj) {
  7. copy[p] = obj[p]
  8. }
  9. // 返回的新对象就是浅拷贝后的对象
  10. return copy
  11. } else {
  12. // 如果是基本类型,直接返回
  13. return obj
  14. }
  15. }

2. 深拷贝

方式一:浅拷贝 + 递归。

  1. // 递归浅拷贝
  2. function recursiveShallowCopy(obj) {
  3. var copy = Array.isArray(obj) ? [] : {};
  4. for (let p in obj) {
  5. if (typeof obj[p] === 'object') {
  6. // 对象类型,继续递归浅拷贝
  7. copy[p] = recursiveShallowCopy(obj[p]);
  8. } else {
  9. copy[p] = obj[p];
  10. }
  11. }
  12. return copy;
  13. }
  14. // 深拷贝
  15. function deepCopy(obj) {
  16. if (typeof obj === 'object' && obj !== null) {
  17. // 如果是引用类型,进行递归浅拷贝
  18. return recursiveShallowCopy(obj);
  19. } else {
  20. // 如果是基本类型,直接返回
  21. return obj;
  22. }
  23. }

方式二:

先通过JSON.stringify()把原对象序列化成一个 JSON 字符串,再通过JSON.parse()生成一个新对象。

更进一步:有同学总结的惊艳面试官的深拷贝实现: