如何在 JS 中复制对象 - 像五岁孩子一样讲解

33 阅读2分钟

听起来很简单,对吧? “你只需要写 const b = a 就行了,对吧?”

然而...很多人在面试中都犯了错误😅

为什么? 因为在 JavaScript 中,“复制对象”的含义并不总是像你想象的那样。 让我们来分解一下——就像我们五岁一样。🍪

1️⃣ 通过引用复制(又名:它实际上不是复制😬) 看看这个:

const cat = { name: "Mittens", age: 3 }; const otherCat = cat;

otherCat.age = 5;

console.log(cat.age); // 😿 5 等等,什么?! 我们以为我们创建了一只新猫, 但两个变量都指向同一只猫。

这是因为 const b = a 不会复制任何内容 — — 它只是说:

“嘿,b 和 a 是同一个对象。”

这叫做通过引用复制。 就像在同一个盒子上贴两个名牌🏷️📦——标签不同,但里面的东西一样。

2️⃣ 展开运算符 (...) — 看起来像魔术,但它只是表面的🪄 你可能已经见过这个技巧:

const newCat = { ...cat }; 并且成功了!😻 修改 newCat 不会改变 cat 的值:

newCat.age = 7; console.log(cat.age); // 🐾 3 不错!但这叫做浅拷贝。 扩展运算符只会复制对象的第一层。

看这里:

const cat = { name: "Mittens", owner: { name: "Anna" } };

const newCat = { ...cat }; newCat.owner.name = "Beth";

console.log(cat.owner.name); // 😿 "Beth" 哎呀! 这是因为 owner 是一个对象内部的对象, 而内部的对象仍然是相同的引用。

💡与数组的工作方式相同:

const arr = [1, 2, 3]; const newArr = [...arr]; 这也是一个浅拷贝。

3️⃣ Object.assign() — 老式的浅拷贝🧓 在扩展运算符流行起来之前,人们这样做:

const newCat = Object.assign({}, cat); 它的作用与 { ...cat } 相同。 仍然是浅拷贝——只复制顶层。

4️⃣ 深度复制 — — 真正的新猫🐱🐱 如果您想要一个真正的克隆,包括嵌套在其中的所有内容,那么 您需要一个深层复制。

a) 经典方法(JSON技巧)

const newCat = JSON.parse(JSON.stringify(cat)); ✔️ 非常适合处理简单数据(字符串、数字、数组、普通对象) 。❌ 但是会丢失函数、日期、未定义、符号、Map、Set 等数据。❌ 循环引用也会失败:

const cat = {}; cat.friend = cat; JSON.stringify(cat); // ❌ TypeError: Converting circular structure to JSON 丢失数据的示例:

const cat = { birthday: new Date(), speak: () => "meow" };

const copy = JSON.parse(JSON.stringify(cat)); console.log(copy); // { birthday: "2025-10-16T08:00:00.000Z" } — function is gone, date is now a string 😿 b) 现代方法:structuredClone()🚀

在较新的 JavaScript(浏览器或 Node 17+)中,您可以使用:

const newCat = structuredClone(cat); 这才是真正的利器。 它可以安全地复制嵌套数据,并保持类型完整——包括 Date、Map、Set、ArrayBuffer、Blob 等。

例子:

const cat = { birthday: new Date(), toys: new Set(["ball", "mouse"]) }; const copy = structuredClone(cat);

console.log(copy.birthday instanceof Date); // ✅ true console.log(copy.toys.has("ball")); // ✅ true 5️⃣ TL;DR(又名:你的面试备忘单😉)

方法 副本类型 适用于嵌套对象吗? 笔记 const b = a 🔗 参考 ❌ 同一对象 { ...a } 🪞 浅 ❌ 常见的面试陷阱 Object.assign({}, a) 🪞 浅 ❌ 老式传播 JSON.parse(JSON.stringify(a)) 📦深 ✅ 丢失函数、日期,循环引用失败 structuredClone(a) 🚀 深 ✅ 现代、安全、支持复杂类型 ✨ 故事寓意 在复制一个对象之前,问问自己: 我想要一个新标签,还是一个全新的盒子。作者www.youjiutian.com