javascript深拷贝与浅拷贝:对象复制的奥秘

夸克资源分享:
表情包:https://pan.quark.cn/s/5b9ddeb237fe
工具箱:https://pan.quark.cn/s/aa2d6a730482,图吧、美蛋、路遥、入梦等
Fiddler Everywhere抓包:https://pan.quark.cn/s/6b1e2fbae019
Adobe:https://pan.quark.cn/s/13e39cfeaadb,先看安装教程
JetBranis开发者工具:https://pan.quark.cn/s/16e94dcff1f7,先看安装教程下的jetbra教程
逆向工具:https://pan.quark.cn/s/50e93c8ca54c
前端项目搭建集锦:https://blog.youkuaiyun.com/randy521520/article/details/146998467

一、简介

        在编程的世界中,对象的复制是一项基础而重要的操作。深拷贝与浅拷贝,这两种复制方式各有千秋。
        深拷贝,宛如一位技艺精湛的工匠,精心打造一个全新的对象。它不遗余力地完全复制原对象的所有属性,无论是错综复杂的嵌套对象,还是数组,都无一例外。如此一来,新对象与原对象宛如两个独立的个体,彼此间毫无关联。即便对新生对象进行大刀阔斧的修改,原对象也能安然无恙,丝毫不会受到影响。
        浅拷贝则像是一个高效的助手,迅速创建一个新对象,仅仅复制原对象的第一层属性。若属性是基本类型,它便复制其值;而若是引用类型,它就复制引用地址,这意味着新对象与原对象在引用类型属性上共享同一片内存空间。就好比两个人共同拥有一把钥匙,打开的是同一扇门。
        深拷贝与浅拷贝在不同的场景中发挥着各自的作用。当我们渴望创建一个与原对象完全独立、互不影响的新对象时,深拷贝便是我们的得力助手;而在某些对性能要求较高,且不需要完全独立的场景下,浅拷贝则能大显身手。
        理解深拷贝与浅拷贝的区别,对于编写高效、可靠的代码至关重要。它犹如为我们打开了一扇通往编程深处的大门,让我们能更加自如地驾驭对象的复制操作,为我们的编程之旅增添更多的精彩与可能。在实际应用中,我们要根据具体的需求,谨慎地选择适合的复制方式,让代码在我们的掌控下如行云流水般运行。

特性浅拷贝(Shallow Copy)深拷贝(Deep Copy)
复制层级仅复制对象的第一层属性递归复制对象的所有层级属性
引用类型处理复制引用地址(新旧对象共享嵌套对象)创建全新的嵌套对象(完全独立)
内存占用较少较多
性能较快较慢
循环引用处理不涉及(因为不处理嵌套)不涉及(因为不处理嵌套)需要特殊处理(否则会栈溢出)

二、浅拷贝实现

1.扩展运算符 (Spread Operator)

const original = { a: 1, b: { c: 2 } };
const copy = { ...original };

2.Object.assign()

const original = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, original);

3.Array.prototype.slice() (数组专用)

const originalArray = [1, 2, { a: 3 }];
const copyArray = originalArray.slice();

4.Array.prototype.concat() (数组专用)

const originalArray = [1, 2, { a: 3 }];
const copyArray = [].concat(originalArray);

5.Array.from() (数组专用)

const originalArray = [1, 2, { a: 3 }];
const copyArray = Array.from(originalArray);

6.手动遍历属性

function shallowCopy(obj) {
  const copy = {};
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      copy[key] = obj[key];
    }
  }
  return copy;
}

三、深拷贝实现

1.JSON 序列化反序列化法(最简单但不完美)

/**
不能处理函数、Symbol、undefined等特殊类型
会丢失对象的constructor信息
不能处理循环引用
会忽略Date对象(转为字符串
**/
const deepCopy = obj => JSON.parse(JSON.stringify(obj));

2.递归实现基础版

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') return obj;
  
  const clone = Array.isArray(obj) ? [] : {};
  
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key]);
    }
  }
  
  return clone;
}

3.递归实现增强版:处理循环引用、特殊类型

function deepClone(obj, hash = new WeakMap()) {
  // 处理基本类型和null
  if (obj === null || typeof obj !== 'object') return obj;
  
  // 处理循环引用
  if (hash.has(obj)) return hash.get(obj);
  
  // 处理Date
  if (obj instanceof Date) return new Date(obj);
  
  // 处理RegExp
  if (obj instanceof RegExp) return new RegExp(obj);
  
  // 处理Map
  if (obj instanceof Map) {
    const clone = new Map();
    hash.set(obj, clone);
    obj.forEach((value, key) => {
      clone.set(key, deepClone(value, hash));
    });
    return clone;
  }
  
  // 处理Set
  if (obj instanceof Set) {
    const clone = new Set();
    hash.set(obj, clone);
    obj.forEach(value => {
      clone.add(deepClone(value, hash));
    });
    return clone;
  }
  
  // 处理数组和普通对象
  const clone = Array.isArray(obj) ? [] : {};
  hash.set(obj, clone);
  
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      clone[key] = deepClone(obj[key], hash);
    }
  }
  
  return clone;
}

4.结构化克隆 structuredClone()

// 原始对象,包含嵌套数据
const sourceData = { 
  id: 101, 
  name: "Example", 
  details: { 
    value: "Nested Data" 
  } 
};

// 使用 structuredClone() 进行深拷贝
const clonedData = structuredClone(sourceData);

5.使用第三方库:lodash

import _ from 'lodash'; 

const original = {
  name: "Alice",
  details: {
    age: 25,
    skills: ["JavaScript", "React"]
  }
};

// 深拷贝
const cloned = _.cloneDeep(original);  // 全量引入方式
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

局外人LZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值