使用Object.assign时原对象值被覆盖,如何安全修改person1.name.first?
解决Object.assign()修改嵌套属性时覆盖原对象的问题
嘿,这个问题我太熟了!Object.assign()的坑就在于它是浅拷贝——只会复制对象的顶层属性,嵌套的对象还是共享同一个引用,所以你修改新对象的嵌套属性时,原蓝图对象也跟着变了。要保护原对象不被修改,我们需要确保嵌套层级的对象也是新的副本,下面给你几个实用的解决方案:
方案1:用展开运算符(...)逐层拷贝嵌套对象
如果你的对象嵌套层级不多,这种方式最清晰,能精准控制要修改的属性:
假设你的蓝图对象是这样的:
const blueprintPerson = { name: { first: "John", last: "Doe" }, age: 30 };
要创建修改name.first后的person1,同时不改动原蓝图:
const person1 = { // 先拷贝顶层所有属性 ...blueprintPerson, // 单独处理name属性:先拷贝原name的所有属性,再覆盖first name: { ...blueprintPerson.name, first: "Jane" } };
这样person1.name是一个全新的对象,和blueprintPerson.name不再共享引用,修改person1.name.first完全不会影响原蓝图。
方案2:用structuredClone()做深拷贝
如果你的对象嵌套层级比较深,或者不想手动逐层展开,用ES2022新增的structuredClone()最省心,它能递归复制整个对象的所有层级:
const person1 = structuredClone(blueprintPerson); // 现在随便修改嵌套属性,原蓝图毫发无损 person1.name.first = "Jane";
这个方法支持大多数数据类型(对象、数组、Date、Map等),现代浏览器和Node.js 17+都支持,简单粗暴还靠谱。
方案3:自定义深拷贝函数(兼容旧环境)
如果需要兼容不支持structuredClone()的旧环境,可以自己写一个简单的深拷贝函数:
function deepClone(obj) { // 非对象类型直接返回 if (obj === null || typeof obj !== "object") return obj; // 处理Date对象 if (obj instanceof Date) return new Date(obj.getTime()); // 处理数组 if (obj instanceof Array) return obj.map(item => deepClone(item)); // 处理普通对象 const clonedObj = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { clonedObj[key] = deepClone(obj[key]); } } return clonedObj; } // 使用方式 const person1 = deepClone(blueprintPerson); person1.name.first = "Jane";
总结一下:如果只是修改少数嵌套属性,优先用展开运算符(代码可读性高);如果对象复杂,直接用structuredClone();旧环境就用自定义深拷贝函数。这三种方法都能彻底保护你的蓝图对象不被修改。
内容的提问来源于stack exchange,提问作者Tpn Knvl
相关产品推荐
相关产品推荐

